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(Name: "__APPLE_CC__" , Value: "6000" ); |
26 | Builder.defineMacro(Name: "__APPLE__" ); |
27 | Builder.defineMacro(Name: "__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(K: SanitizerKind::Address)) |
32 | Builder.defineMacro(Name: "_FORTIFY_SOURCE" , Value: "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(Name: "__weak" , Value: "__attribute__((objc_gc(weak)))" ); |
38 | Builder.defineMacro(Name: "__strong" , Value: "" ); |
39 | Builder.defineMacro(Name: "__unsafe_unretained" , Value: "" ); |
40 | } |
41 | |
42 | if (Opts.Static) |
43 | Builder.defineMacro(Name: "__STATIC__" ); |
44 | else |
45 | Builder.defineMacro(Name: "__DYNAMIC__" ); |
46 | |
47 | if (Opts.POSIXThreads) |
48 | Builder.defineMacro(Name: "_REENTRANT" ); |
49 | |
50 | // Get the platform type and version number from the triple. |
51 | VersionTuple OsVersion; |
52 | if (Triple.isMacOSX()) { |
53 | Triple.getMacOSXVersion(Version&: OsVersion); |
54 | PlatformName = "macos" ; |
55 | } else { |
56 | OsVersion = Triple.getOSVersion(); |
57 | PlatformName = llvm::Triple::getOSTypeName(Kind: 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(a: OsVersion.getMinor().value_or(u: 0), b: 9U); |
76 | Str[3] = '0' + std::min(a: OsVersion.getSubminor().value_or(u: 0), b: 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(u: 0) / 10); |
81 | Str[2] = '0' + (OsVersion.getMinor().value_or(u: 0) % 10); |
82 | Str[3] = '0' + (OsVersion.getSubminor().value_or(u: 0) / 10); |
83 | Str[4] = '0' + (OsVersion.getSubminor().value_or(u: 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(u: 0) / 10); |
90 | Str[3] = '0' + (OsVersion.getMinor().value_or(u: 0) % 10); |
91 | Str[4] = '0' + (OsVersion.getSubminor().value_or(u: 0) / 10); |
92 | Str[5] = '0' + (OsVersion.getSubminor().value_or(u: 0) % 10); |
93 | Str[6] = '\0'; |
94 | } |
95 | |
96 | // Set the appropriate OS version define. |
97 | if (Triple.isTvOS()) { |
98 | Builder.defineMacro(Name: "__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__" , Value: Str); |
99 | } else if (Triple.isiOS()) { |
100 | Builder.defineMacro(Name: "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__" , Value: Str); |
101 | } else if (Triple.isWatchOS()) { |
102 | Builder.defineMacro(Name: "__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__" , Value: 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(Name: "__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__" , Value: Str); |
107 | } else if (Triple.isMacOSX()) { |
108 | Builder.defineMacro(Name: "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__" , Value: 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(Name: "__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__" , Value: Str); |
117 | |
118 | // Tell users about the kernel if there is one. |
119 | Builder.defineMacro(Name: "__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, MacroName: "WIN32" , Opts); |
128 | DefineStd(Builder, MacroName: "WINNT" , Opts); |
129 | if (Triple.isArch64Bit()) { |
130 | DefineStd(Builder, MacroName: "WIN64" , Opts); |
131 | Builder.defineMacro(Name: "__MINGW64__" ); |
132 | } |
133 | Builder.defineMacro(Name: "__MSVCRT__" ); |
134 | Builder.defineMacro(Name: "__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(Name: "_CPPRTTI" ); |
142 | |
143 | if (Opts.CXXExceptions) |
144 | Builder.defineMacro(Name: "_CPPUNWIND" ); |
145 | } |
146 | |
147 | if (Opts.Bool) |
148 | Builder.defineMacro(Name: "__BOOL_DEFINED" ); |
149 | |
150 | if (!Opts.CharIsSigned) |
151 | Builder.defineMacro(Name: "_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(Name: "_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(Name: "_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(Name: "_M_FP_FAST" ); |
190 | } else { |
191 | Builder.defineMacro(Name: "_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(Name: "_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(Name: "_MT" ); |
205 | |
206 | if (Opts.MSCompatibilityVersion) { |
207 | Builder.defineMacro(Name: "_MSC_VER" , |
208 | Value: Twine(Opts.MSCompatibilityVersion / 100000)); |
209 | Builder.defineMacro(Name: "_MSC_FULL_VER" , Value: Twine(Opts.MSCompatibilityVersion)); |
210 | // FIXME We cannot encode the revision information into 32-bits |
211 | Builder.defineMacro(Name: "_MSC_BUILD" , Value: Twine(1)); |
212 | |
213 | if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2015)) |
214 | Builder.defineMacro(Name: "_HAS_CHAR16_T_LANGUAGE_SUPPORT" , Value: Twine(1)); |
215 | |
216 | if (Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2015)) { |
217 | if (Opts.CPlusPlus23) |
218 | // TODO update to the proper value. |
219 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "202004L" ); |
220 | else if (Opts.CPlusPlus20) |
221 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "202002L" ); |
222 | else if (Opts.CPlusPlus17) |
223 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "201703L" ); |
224 | else if (Opts.CPlusPlus14) |
225 | Builder.defineMacro(Name: "_MSVC_LANG" , Value: "201402L" ); |
226 | } |
227 | |
228 | if (Opts.isCompatibleWithMSVC(MajorVersion: LangOptions::MSVC2022_3)) |
229 | Builder.defineMacro(Name: "_MSVC_CONSTEXPR_ATTRIBUTE" ); |
230 | } |
231 | |
232 | if (Opts.MicrosoftExt) { |
233 | Builder.defineMacro(Name: "_MSC_EXTENSIONS" ); |
234 | |
235 | if (Opts.CPlusPlus11) { |
236 | Builder.defineMacro(Name: "_RVALUE_REFERENCES_V2_SUPPORTED" ); |
237 | Builder.defineMacro(Name: "_RVALUE_REFERENCES_SUPPORTED" ); |
238 | Builder.defineMacro(Name: "_NATIVE_NULLPTR_SUPPORTED" ); |
239 | } |
240 | } |
241 | |
242 | if (!Opts.MSVolatile) |
243 | Builder.defineMacro(Name: "_ISO_VOLATILE" ); |
244 | |
245 | if (Opts.Kernel) |
246 | Builder.defineMacro(Name: "_KERNEL_MODE" ); |
247 | |
248 | Builder.defineMacro(Name: "_INTEGRAL_MAX_BITS" , Value: "64" ); |
249 | Builder.defineMacro(Name: "__STDC_NO_THREADS__" ); |
250 | |
251 | // Starting with VS 2022 17.1, MSVC predefines the below macro to inform |
252 | // users of the execution character set defined at compile time. |
253 | // The value given is the Windows Code Page Identifier: |
254 | // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers |
255 | // |
256 | // Clang currently only supports UTF-8, so we'll use 65001 |
257 | Builder.defineMacro(Name: "_MSVC_EXECUTION_CHARACTER_SET" , Value: "65001" ); |
258 | } |
259 | |
260 | void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, |
261 | MacroBuilder &Builder) { |
262 | Builder.defineMacro(Name: "_WIN32" ); |
263 | if (Triple.isArch64Bit()) |
264 | Builder.defineMacro(Name: "_WIN64" ); |
265 | if (Triple.isWindowsGNUEnvironment()) |
266 | addMinGWDefines(Triple, Opts, Builder); |
267 | else if (Triple.isKnownWindowsMSVCEnvironment() || |
268 | (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) |
269 | addVisualCDefines(Opts, Builder); |
270 | } |
271 | |
272 | } // namespace targets |
273 | } // namespace clang |
274 | |