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 // Set the appropriate OS version define. 71 if (Triple.isiOS()) { 72 assert(OsVersion < VersionTuple(100) && "Invalid version!"); 73 char Str[7]; 74 if (OsVersion.getMajor() < 10) { 75 Str[0] = '0' + OsVersion.getMajor(); 76 Str[1] = '0' + (OsVersion.getMinor().value_or(0) / 10); 77 Str[2] = '0' + (OsVersion.getMinor().value_or(0) % 10); 78 Str[3] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 79 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 80 Str[5] = '\0'; 81 } else { 82 // Handle versions >= 10. 83 Str[0] = '0' + (OsVersion.getMajor() / 10); 84 Str[1] = '0' + (OsVersion.getMajor() % 10); 85 Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); 86 Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); 87 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 88 Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 89 Str[6] = '\0'; 90 } 91 if (Triple.isTvOS()) 92 Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str); 93 else 94 Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", 95 Str); 96 97 } else if (Triple.isWatchOS()) { 98 assert(OsVersion < VersionTuple(10) && "Invalid version!"); 99 char Str[6]; 100 Str[0] = '0' + OsVersion.getMajor(); 101 Str[1] = '0' + (OsVersion.getMinor().value_or(0) / 10); 102 Str[2] = '0' + (OsVersion.getMinor().value_or(0) % 10); 103 Str[3] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 104 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 105 Str[5] = '\0'; 106 Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str); 107 } else if (Triple.isDriverKit()) { 108 assert(OsVersion.getMajor() < 100 && 109 OsVersion.getMinor().value_or(0) < 100 && 110 OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); 111 char Str[7]; 112 Str[0] = '0' + (OsVersion.getMajor() / 10); 113 Str[1] = '0' + (OsVersion.getMajor() % 10); 114 Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); 115 Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); 116 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 117 Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 118 Str[6] = '\0'; 119 Builder.defineMacro("__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__", Str); 120 } else if (Triple.isMacOSX()) { 121 // Note that the Driver allows versions which aren't representable in the 122 // define (because we only get a single digit for the minor and micro 123 // revision numbers). So, we limit them to the maximum representable 124 // version. 125 assert(OsVersion < VersionTuple(100) && "Invalid version!"); 126 char Str[7]; 127 if (OsVersion < VersionTuple(10, 10)) { 128 Str[0] = '0' + (OsVersion.getMajor() / 10); 129 Str[1] = '0' + (OsVersion.getMajor() % 10); 130 Str[2] = '0' + std::min(OsVersion.getMinor().value_or(0), 9U); 131 Str[3] = '0' + std::min(OsVersion.getSubminor().value_or(0), 9U); 132 Str[4] = '\0'; 133 } else { 134 // Handle versions > 10.9. 135 Str[0] = '0' + (OsVersion.getMajor() / 10); 136 Str[1] = '0' + (OsVersion.getMajor() % 10); 137 Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); 138 Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); 139 Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); 140 Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); 141 Str[6] = '\0'; 142 } 143 Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); 144 } 145 146 // Tell users about the kernel if there is one. 147 if (Triple.isOSDarwin()) 148 Builder.defineMacro("__MACH__"); 149 150 PlatformMinVersion = OsVersion; 151 } 152 153 static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts, 154 MacroBuilder &Builder) { 155 DefineStd(Builder, "WIN32", Opts); 156 DefineStd(Builder, "WINNT", Opts); 157 if (Triple.isArch64Bit()) { 158 DefineStd(Builder, "WIN64", Opts); 159 Builder.defineMacro("__MINGW64__"); 160 } 161 Builder.defineMacro("__MSVCRT__"); 162 Builder.defineMacro("__MINGW32__"); 163 addCygMingDefines(Opts, Builder); 164 } 165 166 static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { 167 if (Opts.CPlusPlus) { 168 if (Opts.RTTIData) 169 Builder.defineMacro("_CPPRTTI"); 170 171 if (Opts.CXXExceptions) 172 Builder.defineMacro("_CPPUNWIND"); 173 } 174 175 if (Opts.Bool) 176 Builder.defineMacro("__BOOL_DEFINED"); 177 178 if (!Opts.CharIsSigned) 179 Builder.defineMacro("_CHAR_UNSIGNED"); 180 181 // FIXME: POSIXThreads isn't exactly the option this should be defined for, 182 // but it works for now. 183 if (Opts.POSIXThreads) 184 Builder.defineMacro("_MT"); 185 186 if (Opts.MSCompatibilityVersion) { 187 Builder.defineMacro("_MSC_VER", 188 Twine(Opts.MSCompatibilityVersion / 100000)); 189 Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); 190 // FIXME We cannot encode the revision information into 32-bits 191 Builder.defineMacro("_MSC_BUILD", Twine(1)); 192 193 if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) 194 Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); 195 196 if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { 197 if (Opts.CPlusPlus2b) 198 Builder.defineMacro("_MSVC_LANG", "202004L"); 199 else if (Opts.CPlusPlus20) 200 Builder.defineMacro("_MSVC_LANG", "202002L"); 201 else if (Opts.CPlusPlus17) 202 Builder.defineMacro("_MSVC_LANG", "201703L"); 203 else if (Opts.CPlusPlus14) 204 Builder.defineMacro("_MSVC_LANG", "201402L"); 205 } 206 } 207 208 if (Opts.MicrosoftExt) { 209 Builder.defineMacro("_MSC_EXTENSIONS"); 210 211 if (Opts.CPlusPlus11) { 212 Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); 213 Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); 214 Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); 215 } 216 } 217 218 if (Opts.Kernel) 219 Builder.defineMacro("_KERNEL_MODE"); 220 221 Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); 222 Builder.defineMacro("__STDC_NO_THREADS__"); 223 224 // Starting with VS 2022 17.1, MSVC predefines the below macro to inform 225 // users of the execution character set defined at compile time. 226 // The value given is the Windows Code Page Identifier: 227 // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers 228 // 229 // Clang currently only supports UTF-8, so we'll use 65001 230 Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001"); 231 } 232 233 void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, 234 MacroBuilder &Builder) { 235 Builder.defineMacro("_WIN32"); 236 if (Triple.isArch64Bit()) 237 Builder.defineMacro("_WIN64"); 238 if (Triple.isWindowsGNUEnvironment()) 239 addMinGWDefines(Triple, Opts, Builder); 240 else if (Triple.isKnownWindowsMSVCEnvironment() || 241 (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) 242 addVisualCDefines(Opts, Builder); 243 } 244 245 } // namespace targets 246 } // namespace clang 247