1 //===--- OSTargets.cpp - Implement OS target feature support --------------===// 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 implements OS specific TargetInfo types. 10 //===----------------------------------------------------------------------===// 11 12 #include "OSTargets.h" 13 #include "clang/Basic/MacroBuilder.h" 14 #include "llvm/ADT/StringRef.h" 15 16 using namespace clang; 17 using namespace clang::targets; 18 19 namespace clang { 20 namespace targets { 21 22 void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, 23 const llvm::Triple &Triple, StringRef &PlatformName, 24 VersionTuple &PlatformMinVersion) { 25 Builder.defineMacro("__APPLE_CC__", "6000"); 26 Builder.defineMacro("__APPLE__"); 27 Builder.defineMacro("__STDC_NO_THREADS__"); 28 29 // AddressSanitizer doesn't play well with source fortification, which is on 30 // by default on Darwin. 31 if (Opts.Sanitize.has(SanitizerKind::Address)) 32 Builder.defineMacro("_FORTIFY_SOURCE", "0"); 33 34 // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode. 35 if (!Opts.ObjC) { 36 // __weak is always defined, for use in blocks and with objc pointers. 37 Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); 38 Builder.defineMacro("__strong", ""); 39 Builder.defineMacro("__unsafe_unretained", ""); 40 } 41 42 if (Opts.Static) 43 Builder.defineMacro("__STATIC__"); 44 else 45 Builder.defineMacro("__DYNAMIC__"); 46 47 if (Opts.POSIXThreads) 48 Builder.defineMacro("_REENTRANT"); 49 50 // Get the platform type and version number from the triple. 51 VersionTuple OsVersion; 52 if (Triple.isMacOSX()) { 53 Triple.getMacOSXVersion(OsVersion); 54 PlatformName = "macos"; 55 } else { 56 OsVersion = Triple.getOSVersion(); 57 PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); 58 if (PlatformName == "ios" && Triple.isMacCatalystEnvironment()) 59 PlatformName = "maccatalyst"; 60 } 61 62 // If -target arch-pc-win32-macho option specified, we're 63 // generating code for Win32 ABI. No need to emit 64 // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__. 65 if (PlatformName == "win32") { 66 PlatformMinVersion = OsVersion; 67 return; 68 } 69 70 assert(OsVersion < VersionTuple(100) && "Invalid version!"); 71 char Str[7]; 72 if (Triple.isMacOSX() && OsVersion < VersionTuple(10, 10)) { 73 Str[0] = '0' + (OsVersion.getMajor() / 10); 74 Str[1] = '0' + (OsVersion.getMajor() % 10); 75 Str[2] = '0' + std::min(OsVersion.getMinor().value_or(0), 9U); 76 Str[3] = '0' + std::min(OsVersion.getSubminor().value_or(0), 9U); 77 Str[4] = '\0'; 78 } else if (!Triple.isMacOSX() && OsVersion.getMajor() < 10) { 79 Str[0] = '0' + OsVersion.getMajor(); 80 Str[1] = '0' + (OsVersion.getMinor().value_or(0) / 10); 81 Str[2] = '0' + (OsVersion.getMinor().value_or(0) % 10); 82 Str[3] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 83 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 84 Str[5] = '\0'; 85 } else { 86 // Handle versions >= 10. 87 Str[0] = '0' + (OsVersion.getMajor() / 10); 88 Str[1] = '0' + (OsVersion.getMajor() % 10); 89 Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); 90 Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); 91 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 92 Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 93 Str[6] = '\0'; 94 } 95 96 // Set the appropriate OS version define. 97 if (Triple.isTvOS()) { 98 Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str); 99 } else if (Triple.isiOS()) { 100 Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str); 101 } else if (Triple.isWatchOS()) { 102 Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str); 103 } else if (Triple.isDriverKit()) { 104 assert(OsVersion.getMinor().value_or(0) < 100 && 105 OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); 106 Builder.defineMacro("__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__", Str); 107 } else if (Triple.isMacOSX()) { 108 Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); 109 } 110 111 // Tell users about the kernel if there is one. 112 if (Triple.isOSDarwin()) 113 Builder.defineMacro("__MACH__"); 114 115 PlatformMinVersion = OsVersion; 116 } 117 118 static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts, 119 MacroBuilder &Builder) { 120 DefineStd(Builder, "WIN32", Opts); 121 DefineStd(Builder, "WINNT", Opts); 122 if (Triple.isArch64Bit()) { 123 DefineStd(Builder, "WIN64", Opts); 124 Builder.defineMacro("__MINGW64__"); 125 } 126 Builder.defineMacro("__MSVCRT__"); 127 Builder.defineMacro("__MINGW32__"); 128 addCygMingDefines(Opts, Builder); 129 } 130 131 static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { 132 if (Opts.CPlusPlus) { 133 if (Opts.RTTIData) 134 Builder.defineMacro("_CPPRTTI"); 135 136 if (Opts.CXXExceptions) 137 Builder.defineMacro("_CPPUNWIND"); 138 } 139 140 if (Opts.Bool) 141 Builder.defineMacro("__BOOL_DEFINED"); 142 143 if (!Opts.CharIsSigned) 144 Builder.defineMacro("_CHAR_UNSIGNED"); 145 146 // "The /fp:contract option allows the compiler to generate floating-point 147 // contractions [...]" 148 if (Opts.getDefaultFPContractMode() != LangOptions::FPModeKind::FPM_Off) 149 Builder.defineMacro("_M_FP_CONTRACT"); 150 151 // "The /fp:except option generates code to ensures that any unmasked 152 // floating-point exceptions are raised at the exact point at which they 153 // occur, and that no other floating-point exceptions are raised." 154 if (Opts.getDefaultExceptionMode() == 155 LangOptions::FPExceptionModeKind::FPE_Strict) 156 Builder.defineMacro("_M_FP_EXCEPT"); 157 158 // "The /fp:fast option allows the compiler to reorder, combine, or simplify 159 // floating-point operations to optimize floating-point code for speed and 160 // space. The compiler may omit rounding at assignment statements, 161 // typecasts, or function calls. It may reorder operations or make algebraic 162 // transforms, for example, by use of associative and distributive laws. It 163 // may reorder code even if such transformations result in observably 164 // different rounding behavior." 165 // 166 // "Under /fp:precise and /fp:strict, the compiler doesn't do any mathematical 167 // transformation unless the transformation is guaranteed to produce a bitwise 168 // identical result." 169 const bool any_imprecise_flags = 170 Opts.FastMath || Opts.FiniteMathOnly || Opts.UnsafeFPMath || 171 Opts.AllowFPReassoc || Opts.NoHonorNaNs || Opts.NoHonorInfs || 172 Opts.NoSignedZero || Opts.AllowRecip || Opts.ApproxFunc; 173 174 // "Under both /fp:precise and /fp:fast, the compiler generates code intended 175 // to run in the default floating-point environment." 176 // 177 // "[The] default floating point environment [...] sets the rounding mode 178 // to round to nearest." 179 if (Opts.getDefaultRoundingMode() == 180 LangOptions::RoundingMode::NearestTiesToEven) { 181 if (any_imprecise_flags) { 182 Builder.defineMacro("_M_FP_FAST"); 183 } else { 184 Builder.defineMacro("_M_FP_PRECISE"); 185 } 186 } else if (!any_imprecise_flags && Opts.getDefaultRoundingMode() == 187 LangOptions::RoundingMode::Dynamic) { 188 // "Under /fp:strict, the compiler generates code that allows the 189 // program to safely unmask floating-point exceptions, read or write 190 // floating-point status registers, or change rounding modes." 191 Builder.defineMacro("_M_FP_STRICT"); 192 } 193 194 // FIXME: POSIXThreads isn't exactly the option this should be defined for, 195 // but it works for now. 196 if (Opts.POSIXThreads) 197 Builder.defineMacro("_MT"); 198 199 if (Opts.MSCompatibilityVersion) { 200 Builder.defineMacro("_MSC_VER", 201 Twine(Opts.MSCompatibilityVersion / 100000)); 202 Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); 203 // FIXME We cannot encode the revision information into 32-bits 204 Builder.defineMacro("_MSC_BUILD", Twine(1)); 205 206 if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) 207 Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); 208 209 if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { 210 if (Opts.CPlusPlus2b) 211 Builder.defineMacro("_MSVC_LANG", "202004L"); 212 else if (Opts.CPlusPlus20) 213 Builder.defineMacro("_MSVC_LANG", "202002L"); 214 else if (Opts.CPlusPlus17) 215 Builder.defineMacro("_MSVC_LANG", "201703L"); 216 else if (Opts.CPlusPlus14) 217 Builder.defineMacro("_MSVC_LANG", "201402L"); 218 } 219 } 220 221 if (Opts.MicrosoftExt) { 222 Builder.defineMacro("_MSC_EXTENSIONS"); 223 224 if (Opts.CPlusPlus11) { 225 Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); 226 Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); 227 Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); 228 } 229 } 230 231 if (!Opts.MSVolatile) 232 Builder.defineMacro("_ISO_VOLATILE"); 233 234 if (Opts.Kernel) 235 Builder.defineMacro("_KERNEL_MODE"); 236 237 Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); 238 Builder.defineMacro("__STDC_NO_THREADS__"); 239 240 // Starting with VS 2022 17.1, MSVC predefines the below macro to inform 241 // users of the execution character set defined at compile time. 242 // The value given is the Windows Code Page Identifier: 243 // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers 244 // 245 // Clang currently only supports UTF-8, so we'll use 65001 246 Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001"); 247 } 248 249 void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, 250 MacroBuilder &Builder) { 251 Builder.defineMacro("_WIN32"); 252 if (Triple.isArch64Bit()) 253 Builder.defineMacro("_WIN64"); 254 if (Triple.isWindowsGNUEnvironment()) 255 addMinGWDefines(Triple, Opts, Builder); 256 else if (Triple.isKnownWindowsMSVCEnvironment() || 257 (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) 258 addVisualCDefines(Opts, Builder); 259 } 260 261 } // namespace targets 262 } // namespace clang 263