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(Name: "__APPLE_CC__" , Value: "6000" ); |
25 | Builder.defineMacro(Name: "__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(K: SanitizerKind::Address)) |
30 | Builder.defineMacro(Name: "_FORTIFY_SOURCE" , Value: "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(Name: "__weak" , Value: "__attribute__((objc_gc(weak)))" ); |
36 | Builder.defineMacro(Name: "__strong" , Value: "" ); |
37 | Builder.defineMacro(Name: "__unsafe_unretained" , Value: "" ); |
38 | } |
39 | |
40 | if (Opts.Static) |
41 | Builder.defineMacro(Name: "__STATIC__" ); |
42 | else |
43 | Builder.defineMacro(Name: "__DYNAMIC__" ); |
44 | |
45 | if (Opts.POSIXThreads) |
46 | Builder.defineMacro(Name: "_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(Name: "__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(Name: "__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(Version&: OsVersion); |
68 | PlatformName = "macos" ; |
69 | } else { |
70 | OsVersion = Triple.getOSVersion(); |
71 | PlatformName = llvm::Triple::getOSTypeName(Kind: 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(a: OsVersion.getMinor().value_or(u: 0), b: 9U); |
90 | Str[3] = '0' + std::min(a: OsVersion.getSubminor().value_or(u: 0), b: 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(u: 0) / 10); |
95 | Str[2] = '0' + (OsVersion.getMinor().value_or(u: 0) % 10); |
96 | Str[3] = '0' + (OsVersion.getSubminor().value_or(u: 0) / 10); |
97 | Str[4] = '0' + (OsVersion.getSubminor().value_or(u: 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(u: 0) / 10); |
104 | Str[3] = '0' + (OsVersion.getMinor().value_or(u: 0) % 10); |
105 | Str[4] = '0' + (OsVersion.getSubminor().value_or(u: 0) / 10); |
106 | Str[5] = '0' + (OsVersion.getSubminor().value_or(u: 0) % 10); |
107 | Str[6] = '\0'; |
108 | } |
109 | |
110 | // Set the appropriate OS version define. |
111 | if (Triple.isTvOS()) { |
112 | Builder.defineMacro(Name: "__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__" , Value: Str); |
113 | } else if (Triple.isiOS()) { |
114 | Builder.defineMacro(Name: "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__" , Value: Str); |
115 | } else if (Triple.isWatchOS()) { |
116 | Builder.defineMacro(Name: "__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__" , Value: 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(Name: "__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__" , Value: Str); |
121 | } else if (Triple.isMacOSX()) { |
122 | Builder.defineMacro(Name: "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__" , Value: 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(Name: "__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__" , Value: 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, MacroName: "WIN32" , Opts); |
139 | DefineStd(Builder, MacroName: "WINNT" , Opts); |
140 | if (Triple.isArch64Bit()) { |
141 | DefineStd(Builder, MacroName: "WIN64" , Opts); |
142 | Builder.defineMacro(Name: "__MINGW64__" ); |
143 | } |
144 | Builder.defineMacro(Name: "__MSVCRT__" ); |
145 | Builder.defineMacro(Name: "__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(Name: "_CPPRTTI" ); |
153 | |
154 | if (Opts.CXXExceptions) |
155 | Builder.defineMacro(Name: "_CPPUNWIND" ); |
156 | } |
157 | |
158 | if (Opts.Bool) |
159 | Builder.defineMacro(Name: "__BOOL_DEFINED" ); |
160 | |
161 | if (!Opts.CharIsSigned) |
162 | Builder.defineMacro(Name: "_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(Name: "_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(Name: "_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(Name: "_M_FP_FAST" ); |
201 | } else { |
202 | Builder.defineMacro(Name: "_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(Name: "_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(Name: "_MT" ); |
216 | |
217 | if (Opts.MSCompatibilityVersion) { |
218 | Builder.defineMacro(Name: "_MSC_VER" , |
219 | Value: Twine(Opts.MSCompatibilityVersion / 100000)); |
220 | Builder.defineMacro(Name: "_MSC_FULL_VER" , Value: Twine(Opts.MSCompatibilityVersion)); |
221 | // FIXME We cannot encode the revision information into 32-bits |
222 | Builder.defineMacro(Name: "_MSC_BUILD" , Value: Twine(1)); |
223 | // Exposed by MSVC, used in their stddef.h. |
224 | Builder.defineMacro(Name: "_CRT_USE_BUILTIN_OFFSETOF" , Value: Twine(1)); |
225 | |
226 | if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2015)) |
227 | Builder.defineMacro(Name: "_HAS_CHAR16_T_LANGUAGE_SUPPORT" , Value: Twine(1)); |
228 | |
229 | if (Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2015)) { |
230 | if (Opts.CPlusPlus26) |
231 | // TODO update to the proper value. |
232 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "202400L" ); |
233 | else if (Opts.CPlusPlus23) |
234 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "202302L" ); |
235 | else if (Opts.CPlusPlus20) |
236 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "202002L" ); |
237 | else if (Opts.CPlusPlus17) |
238 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "201703L" ); |
239 | else if (Opts.CPlusPlus14) |
240 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "201402L" ); |
241 | } |
242 | |
243 | if (Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2022_3)) |
244 | Builder.defineMacro(Name: "_MSVC_CONSTEXPR_ATTRIBUTE" ); |
245 | } |
246 | |
247 | if (Opts.MicrosoftExt) { |
248 | Builder.defineMacro(Name: "_MSC_EXTENSIONS" ); |
249 | |
250 | if (Opts.CPlusPlus11) { |
251 | Builder.defineMacro(Name: "_RVALUE_REFERENCES_V2_SUPPORTED" ); |
252 | Builder.defineMacro(Name: "_RVALUE_REFERENCES_SUPPORTED" ); |
253 | Builder.defineMacro(Name: "_NATIVE_NULLPTR_SUPPORTED" ); |
254 | } |
255 | } |
256 | |
257 | if (!Opts.MSVolatile) |
258 | Builder.defineMacro(Name: "_ISO_VOLATILE" ); |
259 | |
260 | if (Opts.Kernel) |
261 | Builder.defineMacro(Name: "_KERNEL_MODE" ); |
262 | |
263 | Builder.defineMacro(Name: "_INTEGRAL_MAX_BITS" , Value: "64" ); |
264 | // Define __STDC_NO_THREADS__ based on MSVC version, threads.h availability, |
265 | // and language standard. |
266 | if (!(Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2022_9) && Opts.C11)) |
267 | Builder.defineMacro(Name: "__STDC_NO_THREADS__" ); |
268 | // Starting with VS 2022 17.1, MSVC predefines the below macro to inform |
269 | // users of the execution character set defined at compile time. |
270 | // The value given is the Windows Code Page Identifier: |
271 | // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers |
272 | // |
273 | // Clang currently only supports UTF-8, so we'll use 65001 |
274 | Builder.defineMacro(Name: "_MSVC_EXECUTION_CHARACTER_SET" , Value: "65001" ); |
275 | } |
276 | |
277 | void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, |
278 | MacroBuilder &Builder) { |
279 | Builder.defineMacro(Name: "_WIN32" ); |
280 | if (Triple.isArch64Bit()) |
281 | Builder.defineMacro(Name: "_WIN64" ); |
282 | if (Triple.isWindowsGNUEnvironment()) |
283 | addMinGWDefines(Triple, Opts, Builder); |
284 | else if (Triple.isKnownWindowsMSVCEnvironment() || |
285 | (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) |
286 | addVisualCDefines(Opts, Builder); |
287 | } |
288 | |
289 | } // namespace targets |
290 | } // namespace clang |
291 | |