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