10b57cec5SDimitry Andric //===--- OSTargets.cpp - Implement OS target feature support --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements OS specific TargetInfo types. 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "OSTargets.h" 130b57cec5SDimitry Andric #include "clang/Basic/MacroBuilder.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric using namespace clang; 170b57cec5SDimitry Andric using namespace clang::targets; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace clang { 200b57cec5SDimitry Andric namespace targets { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, 230b57cec5SDimitry Andric const llvm::Triple &Triple, StringRef &PlatformName, 240b57cec5SDimitry Andric VersionTuple &PlatformMinVersion) { 250b57cec5SDimitry Andric Builder.defineMacro("__APPLE_CC__", "6000"); 260b57cec5SDimitry Andric Builder.defineMacro("__APPLE__"); 270b57cec5SDimitry Andric Builder.defineMacro("__STDC_NO_THREADS__"); 285ffd83dbSDimitry Andric 290b57cec5SDimitry Andric // AddressSanitizer doesn't play well with source fortification, which is on 300b57cec5SDimitry Andric // by default on Darwin. 310b57cec5SDimitry Andric if (Opts.Sanitize.has(SanitizerKind::Address)) 320b57cec5SDimitry Andric Builder.defineMacro("_FORTIFY_SOURCE", "0"); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode. 350b57cec5SDimitry Andric if (!Opts.ObjC) { 360b57cec5SDimitry Andric // __weak is always defined, for use in blocks and with objc pointers. 370b57cec5SDimitry Andric Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); 380b57cec5SDimitry Andric Builder.defineMacro("__strong", ""); 390b57cec5SDimitry Andric Builder.defineMacro("__unsafe_unretained", ""); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric if (Opts.Static) 430b57cec5SDimitry Andric Builder.defineMacro("__STATIC__"); 440b57cec5SDimitry Andric else 450b57cec5SDimitry Andric Builder.defineMacro("__DYNAMIC__"); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric if (Opts.POSIXThreads) 480b57cec5SDimitry Andric Builder.defineMacro("_REENTRANT"); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Get the platform type and version number from the triple. 510eae32dcSDimitry Andric VersionTuple OsVersion; 520b57cec5SDimitry Andric if (Triple.isMacOSX()) { 530eae32dcSDimitry Andric Triple.getMacOSXVersion(OsVersion); 540b57cec5SDimitry Andric PlatformName = "macos"; 550b57cec5SDimitry Andric } else { 560eae32dcSDimitry Andric OsVersion = Triple.getOSVersion(); 570b57cec5SDimitry Andric PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); 58fe6060f1SDimitry Andric if (PlatformName == "ios" && Triple.isMacCatalystEnvironment()) 59fe6060f1SDimitry Andric PlatformName = "maccatalyst"; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // If -target arch-pc-win32-macho option specified, we're 630b57cec5SDimitry Andric // generating code for Win32 ABI. No need to emit 640b57cec5SDimitry Andric // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__. 650b57cec5SDimitry Andric if (PlatformName == "win32") { 660eae32dcSDimitry Andric PlatformMinVersion = OsVersion; 670b57cec5SDimitry Andric return; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700eae32dcSDimitry Andric assert(OsVersion < VersionTuple(100) && "Invalid version!"); 710b57cec5SDimitry Andric char Str[7]; 72bdd1243dSDimitry Andric if (Triple.isMacOSX() && OsVersion < VersionTuple(10, 10)) { 73bdd1243dSDimitry Andric Str[0] = '0' + (OsVersion.getMajor() / 10); 74bdd1243dSDimitry Andric Str[1] = '0' + (OsVersion.getMajor() % 10); 75bdd1243dSDimitry Andric Str[2] = '0' + std::min(OsVersion.getMinor().value_or(0), 9U); 76bdd1243dSDimitry Andric Str[3] = '0' + std::min(OsVersion.getSubminor().value_or(0), 9U); 77bdd1243dSDimitry Andric Str[4] = '\0'; 78bdd1243dSDimitry Andric } else if (!Triple.isMacOSX() && OsVersion.getMajor() < 10) { 790eae32dcSDimitry Andric Str[0] = '0' + OsVersion.getMajor(); 8081ad6265SDimitry Andric Str[1] = '0' + (OsVersion.getMinor().value_or(0) / 10); 8181ad6265SDimitry Andric Str[2] = '0' + (OsVersion.getMinor().value_or(0) % 10); 8281ad6265SDimitry Andric Str[3] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 8381ad6265SDimitry Andric Str[4] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 840b57cec5SDimitry Andric Str[5] = '\0'; 850b57cec5SDimitry Andric } else { 860b57cec5SDimitry Andric // Handle versions >= 10. 870eae32dcSDimitry Andric Str[0] = '0' + (OsVersion.getMajor() / 10); 880eae32dcSDimitry Andric Str[1] = '0' + (OsVersion.getMajor() % 10); 8981ad6265SDimitry Andric Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); 9081ad6265SDimitry Andric Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); 9181ad6265SDimitry Andric Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 9281ad6265SDimitry Andric Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 930b57cec5SDimitry Andric Str[6] = '\0'; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 96bdd1243dSDimitry Andric // Set the appropriate OS version define. 97bdd1243dSDimitry Andric if (Triple.isTvOS()) { 98bdd1243dSDimitry Andric Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str); 99bdd1243dSDimitry Andric } else if (Triple.isiOS()) { 100bdd1243dSDimitry Andric Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str); 1010b57cec5SDimitry Andric } else if (Triple.isWatchOS()) { 1020b57cec5SDimitry Andric Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str); 10381ad6265SDimitry Andric } else if (Triple.isDriverKit()) { 104bdd1243dSDimitry Andric assert(OsVersion.getMinor().value_or(0) < 100 && 10581ad6265SDimitry Andric OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); 10681ad6265SDimitry Andric Builder.defineMacro("__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__", Str); 1070b57cec5SDimitry Andric } else if (Triple.isMacOSX()) { 1080b57cec5SDimitry Andric Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 11106c3fb27SDimitry Andric if (Triple.isOSDarwin()) { 11206c3fb27SDimitry Andric // Any darwin OS defines a general darwin OS version macro in addition 11306c3fb27SDimitry Andric // to the other OS specific macros. 11406c3fb27SDimitry Andric assert(OsVersion.getMinor().value_or(0) < 100 && 11506c3fb27SDimitry Andric OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); 11606c3fb27SDimitry Andric Builder.defineMacro("__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__", Str); 11706c3fb27SDimitry Andric 1180b57cec5SDimitry Andric // Tell users about the kernel if there is one. 1190b57cec5SDimitry Andric Builder.defineMacro("__MACH__"); 12006c3fb27SDimitry Andric } 1210b57cec5SDimitry Andric 1220eae32dcSDimitry Andric PlatformMinVersion = OsVersion; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts, 1260b57cec5SDimitry Andric MacroBuilder &Builder) { 1270b57cec5SDimitry Andric DefineStd(Builder, "WIN32", Opts); 1280b57cec5SDimitry Andric DefineStd(Builder, "WINNT", Opts); 1290b57cec5SDimitry Andric if (Triple.isArch64Bit()) { 1300b57cec5SDimitry Andric DefineStd(Builder, "WIN64", Opts); 1310b57cec5SDimitry Andric Builder.defineMacro("__MINGW64__"); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric Builder.defineMacro("__MSVCRT__"); 1340b57cec5SDimitry Andric Builder.defineMacro("__MINGW32__"); 1350b57cec5SDimitry Andric addCygMingDefines(Opts, Builder); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { 1390b57cec5SDimitry Andric if (Opts.CPlusPlus) { 1400b57cec5SDimitry Andric if (Opts.RTTIData) 1410b57cec5SDimitry Andric Builder.defineMacro("_CPPRTTI"); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric if (Opts.CXXExceptions) 1440b57cec5SDimitry Andric Builder.defineMacro("_CPPUNWIND"); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (Opts.Bool) 1480b57cec5SDimitry Andric Builder.defineMacro("__BOOL_DEFINED"); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (!Opts.CharIsSigned) 1510b57cec5SDimitry Andric Builder.defineMacro("_CHAR_UNSIGNED"); 1520b57cec5SDimitry Andric 153bdd1243dSDimitry Andric // "The /fp:contract option allows the compiler to generate floating-point 154bdd1243dSDimitry Andric // contractions [...]" 155bdd1243dSDimitry Andric if (Opts.getDefaultFPContractMode() != LangOptions::FPModeKind::FPM_Off) 156bdd1243dSDimitry Andric Builder.defineMacro("_M_FP_CONTRACT"); 157bdd1243dSDimitry Andric 158bdd1243dSDimitry Andric // "The /fp:except option generates code to ensures that any unmasked 159bdd1243dSDimitry Andric // floating-point exceptions are raised at the exact point at which they 160bdd1243dSDimitry Andric // occur, and that no other floating-point exceptions are raised." 161bdd1243dSDimitry Andric if (Opts.getDefaultExceptionMode() == 162bdd1243dSDimitry Andric LangOptions::FPExceptionModeKind::FPE_Strict) 163bdd1243dSDimitry Andric Builder.defineMacro("_M_FP_EXCEPT"); 164bdd1243dSDimitry Andric 165bdd1243dSDimitry Andric // "The /fp:fast option allows the compiler to reorder, combine, or simplify 166bdd1243dSDimitry Andric // floating-point operations to optimize floating-point code for speed and 167bdd1243dSDimitry Andric // space. The compiler may omit rounding at assignment statements, 168bdd1243dSDimitry Andric // typecasts, or function calls. It may reorder operations or make algebraic 169bdd1243dSDimitry Andric // transforms, for example, by use of associative and distributive laws. It 170bdd1243dSDimitry Andric // may reorder code even if such transformations result in observably 171bdd1243dSDimitry Andric // different rounding behavior." 172bdd1243dSDimitry Andric // 173bdd1243dSDimitry Andric // "Under /fp:precise and /fp:strict, the compiler doesn't do any mathematical 174bdd1243dSDimitry Andric // transformation unless the transformation is guaranteed to produce a bitwise 175bdd1243dSDimitry Andric // identical result." 176bdd1243dSDimitry Andric const bool any_imprecise_flags = 177bdd1243dSDimitry Andric Opts.FastMath || Opts.FiniteMathOnly || Opts.UnsafeFPMath || 178bdd1243dSDimitry Andric Opts.AllowFPReassoc || Opts.NoHonorNaNs || Opts.NoHonorInfs || 179bdd1243dSDimitry Andric Opts.NoSignedZero || Opts.AllowRecip || Opts.ApproxFunc; 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric // "Under both /fp:precise and /fp:fast, the compiler generates code intended 182bdd1243dSDimitry Andric // to run in the default floating-point environment." 183bdd1243dSDimitry Andric // 184bdd1243dSDimitry Andric // "[The] default floating point environment [...] sets the rounding mode 185bdd1243dSDimitry Andric // to round to nearest." 186bdd1243dSDimitry Andric if (Opts.getDefaultRoundingMode() == 187bdd1243dSDimitry Andric LangOptions::RoundingMode::NearestTiesToEven) { 188bdd1243dSDimitry Andric if (any_imprecise_flags) { 189bdd1243dSDimitry Andric Builder.defineMacro("_M_FP_FAST"); 190bdd1243dSDimitry Andric } else { 191bdd1243dSDimitry Andric Builder.defineMacro("_M_FP_PRECISE"); 192bdd1243dSDimitry Andric } 193bdd1243dSDimitry Andric } else if (!any_imprecise_flags && Opts.getDefaultRoundingMode() == 194bdd1243dSDimitry Andric LangOptions::RoundingMode::Dynamic) { 195bdd1243dSDimitry Andric // "Under /fp:strict, the compiler generates code that allows the 196bdd1243dSDimitry Andric // program to safely unmask floating-point exceptions, read or write 197bdd1243dSDimitry Andric // floating-point status registers, or change rounding modes." 198bdd1243dSDimitry Andric Builder.defineMacro("_M_FP_STRICT"); 199bdd1243dSDimitry Andric } 200bdd1243dSDimitry Andric 2010b57cec5SDimitry Andric // FIXME: POSIXThreads isn't exactly the option this should be defined for, 2020b57cec5SDimitry Andric // but it works for now. 2030b57cec5SDimitry Andric if (Opts.POSIXThreads) 2040b57cec5SDimitry Andric Builder.defineMacro("_MT"); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric if (Opts.MSCompatibilityVersion) { 2070b57cec5SDimitry Andric Builder.defineMacro("_MSC_VER", 2080b57cec5SDimitry Andric Twine(Opts.MSCompatibilityVersion / 100000)); 2090b57cec5SDimitry Andric Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); 2100b57cec5SDimitry Andric // FIXME We cannot encode the revision information into 32-bits 2110b57cec5SDimitry Andric Builder.defineMacro("_MSC_BUILD", Twine(1)); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) 2140b57cec5SDimitry Andric Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { 21706c3fb27SDimitry Andric if (Opts.CPlusPlus23) 21806c3fb27SDimitry Andric // TODO update to the proper value. 2194824e7fdSDimitry Andric Builder.defineMacro("_MSVC_LANG", "202004L"); 2204824e7fdSDimitry Andric else if (Opts.CPlusPlus20) 2214824e7fdSDimitry Andric Builder.defineMacro("_MSVC_LANG", "202002L"); 2220b57cec5SDimitry Andric else if (Opts.CPlusPlus17) 2230b57cec5SDimitry Andric Builder.defineMacro("_MSVC_LANG", "201703L"); 2240b57cec5SDimitry Andric else if (Opts.CPlusPlus14) 2250b57cec5SDimitry Andric Builder.defineMacro("_MSVC_LANG", "201402L"); 2260b57cec5SDimitry Andric } 227*5f757f3fSDimitry Andric 228*5f757f3fSDimitry Andric if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2022_3)) 229*5f757f3fSDimitry Andric Builder.defineMacro("_MSVC_CONSTEXPR_ATTRIBUTE"); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric if (Opts.MicrosoftExt) { 2330b57cec5SDimitry Andric Builder.defineMacro("_MSC_EXTENSIONS"); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric if (Opts.CPlusPlus11) { 2360b57cec5SDimitry Andric Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); 2370b57cec5SDimitry Andric Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); 2380b57cec5SDimitry Andric Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 242bdd1243dSDimitry Andric if (!Opts.MSVolatile) 243bdd1243dSDimitry Andric Builder.defineMacro("_ISO_VOLATILE"); 244bdd1243dSDimitry Andric 24581ad6265SDimitry Andric if (Opts.Kernel) 24681ad6265SDimitry Andric Builder.defineMacro("_KERNEL_MODE"); 24781ad6265SDimitry Andric 2480b57cec5SDimitry Andric Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); 2490eae32dcSDimitry Andric Builder.defineMacro("__STDC_NO_THREADS__"); 2504824e7fdSDimitry Andric 2514824e7fdSDimitry Andric // Starting with VS 2022 17.1, MSVC predefines the below macro to inform 2524824e7fdSDimitry Andric // users of the execution character set defined at compile time. 2534824e7fdSDimitry Andric // The value given is the Windows Code Page Identifier: 2544824e7fdSDimitry Andric // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers 2554824e7fdSDimitry Andric // 2564824e7fdSDimitry Andric // Clang currently only supports UTF-8, so we'll use 65001 2574824e7fdSDimitry Andric Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001"); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, 2610b57cec5SDimitry Andric MacroBuilder &Builder) { 2620b57cec5SDimitry Andric Builder.defineMacro("_WIN32"); 2630b57cec5SDimitry Andric if (Triple.isArch64Bit()) 2640b57cec5SDimitry Andric Builder.defineMacro("_WIN64"); 2650b57cec5SDimitry Andric if (Triple.isWindowsGNUEnvironment()) 2660b57cec5SDimitry Andric addMinGWDefines(Triple, Opts, Builder); 2670b57cec5SDimitry Andric else if (Triple.isKnownWindowsMSVCEnvironment() || 2680b57cec5SDimitry Andric (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) 2690b57cec5SDimitry Andric addVisualCDefines(Opts, Builder); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric } // namespace targets 2730b57cec5SDimitry Andric } // namespace clang 274