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