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 if (Triple.isOSDarwin()) { 112 // Any darwin OS defines a general darwin OS version macro in addition 113 // to the other OS specific macros. 114 assert(OsVersion.getMinor().value_or(0) < 100 && 115 OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); 116 Builder.defineMacro("__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__", Str); 117 118 // Tell users about the kernel if there is one. 119 Builder.defineMacro("__MACH__"); 120 } 121 122 PlatformMinVersion = OsVersion; 123 } 124 125 static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts, 126 MacroBuilder &Builder) { 127 DefineStd(Builder, "WIN32", Opts); 128 DefineStd(Builder, "WINNT", Opts); 129 if (Triple.isArch64Bit()) { 130 DefineStd(Builder, "WIN64", Opts); 131 Builder.defineMacro("__MINGW64__"); 132 } 133 Builder.defineMacro("__MSVCRT__"); 134 Builder.defineMacro("__MINGW32__"); 135 addCygMingDefines(Opts, Builder); 136 } 137 138 static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { 139 if (Opts.CPlusPlus) { 140 if (Opts.RTTIData) 141 Builder.defineMacro("_CPPRTTI"); 142 143 if (Opts.CXXExceptions) 144 Builder.defineMacro("_CPPUNWIND"); 145 } 146 147 if (Opts.Bool) 148 Builder.defineMacro("__BOOL_DEFINED"); 149 150 if (!Opts.CharIsSigned) 151 Builder.defineMacro("_CHAR_UNSIGNED"); 152 153 // "The /fp:contract option allows the compiler to generate floating-point 154 // contractions [...]" 155 if (Opts.getDefaultFPContractMode() != LangOptions::FPModeKind::FPM_Off) 156 Builder.defineMacro("_M_FP_CONTRACT"); 157 158 // "The /fp:except option generates code to ensures that any unmasked 159 // floating-point exceptions are raised at the exact point at which they 160 // occur, and that no other floating-point exceptions are raised." 161 if (Opts.getDefaultExceptionMode() == 162 LangOptions::FPExceptionModeKind::FPE_Strict) 163 Builder.defineMacro("_M_FP_EXCEPT"); 164 165 // "The /fp:fast option allows the compiler to reorder, combine, or simplify 166 // floating-point operations to optimize floating-point code for speed and 167 // space. The compiler may omit rounding at assignment statements, 168 // typecasts, or function calls. It may reorder operations or make algebraic 169 // transforms, for example, by use of associative and distributive laws. It 170 // may reorder code even if such transformations result in observably 171 // different rounding behavior." 172 // 173 // "Under /fp:precise and /fp:strict, the compiler doesn't do any mathematical 174 // transformation unless the transformation is guaranteed to produce a bitwise 175 // identical result." 176 const bool any_imprecise_flags = 177 Opts.FastMath || Opts.FiniteMathOnly || Opts.UnsafeFPMath || 178 Opts.AllowFPReassoc || Opts.NoHonorNaNs || Opts.NoHonorInfs || 179 Opts.NoSignedZero || Opts.AllowRecip || Opts.ApproxFunc; 180 181 // "Under both /fp:precise and /fp:fast, the compiler generates code intended 182 // to run in the default floating-point environment." 183 // 184 // "[The] default floating point environment [...] sets the rounding mode 185 // to round to nearest." 186 if (Opts.getDefaultRoundingMode() == 187 LangOptions::RoundingMode::NearestTiesToEven) { 188 if (any_imprecise_flags) { 189 Builder.defineMacro("_M_FP_FAST"); 190 } else { 191 Builder.defineMacro("_M_FP_PRECISE"); 192 } 193 } else if (!any_imprecise_flags && Opts.getDefaultRoundingMode() == 194 LangOptions::RoundingMode::Dynamic) { 195 // "Under /fp:strict, the compiler generates code that allows the 196 // program to safely unmask floating-point exceptions, read or write 197 // floating-point status registers, or change rounding modes." 198 Builder.defineMacro("_M_FP_STRICT"); 199 } 200 201 // FIXME: POSIXThreads isn't exactly the option this should be defined for, 202 // but it works for now. 203 if (Opts.POSIXThreads) 204 Builder.defineMacro("_MT"); 205 206 if (Opts.MSCompatibilityVersion) { 207 Builder.defineMacro("_MSC_VER", 208 Twine(Opts.MSCompatibilityVersion / 100000)); 209 Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); 210 // FIXME We cannot encode the revision information into 32-bits 211 Builder.defineMacro("_MSC_BUILD", Twine(1)); 212 213 if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) 214 Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); 215 216 if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { 217 if (Opts.CPlusPlus23) 218 // TODO update to the proper value. 219 Builder.defineMacro("_MSVC_LANG", "202004L"); 220 else if (Opts.CPlusPlus20) 221 Builder.defineMacro("_MSVC_LANG", "202002L"); 222 else if (Opts.CPlusPlus17) 223 Builder.defineMacro("_MSVC_LANG", "201703L"); 224 else if (Opts.CPlusPlus14) 225 Builder.defineMacro("_MSVC_LANG", "201402L"); 226 } 227 } 228 229 if (Opts.MicrosoftExt) { 230 Builder.defineMacro("_MSC_EXTENSIONS"); 231 232 if (Opts.CPlusPlus11) { 233 Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); 234 Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); 235 Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); 236 } 237 } 238 239 if (!Opts.MSVolatile) 240 Builder.defineMacro("_ISO_VOLATILE"); 241 242 if (Opts.Kernel) 243 Builder.defineMacro("_KERNEL_MODE"); 244 245 Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); 246 Builder.defineMacro("__STDC_NO_THREADS__"); 247 248 // Starting with VS 2022 17.1, MSVC predefines the below macro to inform 249 // users of the execution character set defined at compile time. 250 // The value given is the Windows Code Page Identifier: 251 // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers 252 // 253 // Clang currently only supports UTF-8, so we'll use 65001 254 Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001"); 255 } 256 257 void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, 258 MacroBuilder &Builder) { 259 Builder.defineMacro("_WIN32"); 260 if (Triple.isArch64Bit()) 261 Builder.defineMacro("_WIN64"); 262 if (Triple.isWindowsGNUEnvironment()) 263 addMinGWDefines(Triple, Opts, Builder); 264 else if (Triple.isKnownWindowsMSVCEnvironment() || 265 (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) 266 addVisualCDefines(Opts, Builder); 267 } 268 269 } // namespace targets 270 } // namespace clang 271