/src/llvm-project/clang/lib/Basic/Targets/OSTargets.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | VersionTuple &PlatformMinVersion) { |
25 | 0 | Builder.defineMacro("__APPLE_CC__", "6000"); |
26 | 0 | Builder.defineMacro("__APPLE__"); |
27 | 0 | Builder.defineMacro("__STDC_NO_THREADS__"); |
28 | | |
29 | | // AddressSanitizer doesn't play well with source fortification, which is on |
30 | | // by default on Darwin. |
31 | 0 | if (Opts.Sanitize.has(SanitizerKind::Address)) |
32 | 0 | Builder.defineMacro("_FORTIFY_SOURCE", "0"); |
33 | | |
34 | | // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode. |
35 | 0 | if (!Opts.ObjC) { |
36 | | // __weak is always defined, for use in blocks and with objc pointers. |
37 | 0 | Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); |
38 | 0 | Builder.defineMacro("__strong", ""); |
39 | 0 | Builder.defineMacro("__unsafe_unretained", ""); |
40 | 0 | } |
41 | |
|
42 | 0 | if (Opts.Static) |
43 | 0 | Builder.defineMacro("__STATIC__"); |
44 | 0 | else |
45 | 0 | Builder.defineMacro("__DYNAMIC__"); |
46 | |
|
47 | 0 | if (Opts.POSIXThreads) |
48 | 0 | Builder.defineMacro("_REENTRANT"); |
49 | | |
50 | | // Get the platform type and version number from the triple. |
51 | 0 | VersionTuple OsVersion; |
52 | 0 | if (Triple.isMacOSX()) { |
53 | 0 | Triple.getMacOSXVersion(OsVersion); |
54 | 0 | PlatformName = "macos"; |
55 | 0 | } else { |
56 | 0 | OsVersion = Triple.getOSVersion(); |
57 | 0 | PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); |
58 | 0 | if (PlatformName == "ios" && Triple.isMacCatalystEnvironment()) |
59 | 0 | PlatformName = "maccatalyst"; |
60 | 0 | } |
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 | 0 | if (PlatformName == "win32") { |
66 | 0 | PlatformMinVersion = OsVersion; |
67 | 0 | return; |
68 | 0 | } |
69 | | |
70 | 0 | assert(OsVersion < VersionTuple(100) && "Invalid version!"); |
71 | 0 | char Str[7]; |
72 | 0 | if (Triple.isMacOSX() && OsVersion < VersionTuple(10, 10)) { |
73 | 0 | Str[0] = '0' + (OsVersion.getMajor() / 10); |
74 | 0 | Str[1] = '0' + (OsVersion.getMajor() % 10); |
75 | 0 | Str[2] = '0' + std::min(OsVersion.getMinor().value_or(0), 9U); |
76 | 0 | Str[3] = '0' + std::min(OsVersion.getSubminor().value_or(0), 9U); |
77 | 0 | Str[4] = '\0'; |
78 | 0 | } else if (!Triple.isMacOSX() && OsVersion.getMajor() < 10) { |
79 | 0 | Str[0] = '0' + OsVersion.getMajor(); |
80 | 0 | Str[1] = '0' + (OsVersion.getMinor().value_or(0) / 10); |
81 | 0 | Str[2] = '0' + (OsVersion.getMinor().value_or(0) % 10); |
82 | 0 | Str[3] = '0' + (OsVersion.getSubminor().value_or(0) / 10); |
83 | 0 | Str[4] = '0' + (OsVersion.getSubminor().value_or(0) % 10); |
84 | 0 | Str[5] = '\0'; |
85 | 0 | } else { |
86 | | // Handle versions >= 10. |
87 | 0 | Str[0] = '0' + (OsVersion.getMajor() / 10); |
88 | 0 | Str[1] = '0' + (OsVersion.getMajor() % 10); |
89 | 0 | Str[2] = '0' + (OsVersion.getMinor().value_or(0) / 10); |
90 | 0 | Str[3] = '0' + (OsVersion.getMinor().value_or(0) % 10); |
91 | 0 | Str[4] = '0' + (OsVersion.getSubminor().value_or(0) / 10); |
92 | 0 | Str[5] = '0' + (OsVersion.getSubminor().value_or(0) % 10); |
93 | 0 | Str[6] = '\0'; |
94 | 0 | } |
95 | | |
96 | | // Set the appropriate OS version define. |
97 | 0 | if (Triple.isTvOS()) { |
98 | 0 | Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str); |
99 | 0 | } else if (Triple.isiOS()) { |
100 | 0 | Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str); |
101 | 0 | } else if (Triple.isWatchOS()) { |
102 | 0 | Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str); |
103 | 0 | } else if (Triple.isDriverKit()) { |
104 | 0 | assert(OsVersion.getMinor().value_or(0) < 100 && |
105 | 0 | OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); |
106 | 0 | Builder.defineMacro("__ENVIRONMENT_DRIVERKIT_VERSION_MIN_REQUIRED__", Str); |
107 | 0 | } else if (Triple.isMacOSX()) { |
108 | 0 | Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); |
109 | 0 | } |
110 | | |
111 | 0 | if (Triple.isOSDarwin()) { |
112 | | // Any darwin OS defines a general darwin OS version macro in addition |
113 | | // to the other OS specific macros. |
114 | 0 | assert(OsVersion.getMinor().value_or(0) < 100 && |
115 | 0 | OsVersion.getSubminor().value_or(0) < 100 && "Invalid version!"); |
116 | 0 | Builder.defineMacro("__ENVIRONMENT_OS_VERSION_MIN_REQUIRED__", Str); |
117 | | |
118 | | // Tell users about the kernel if there is one. |
119 | 0 | Builder.defineMacro("__MACH__"); |
120 | 0 | } |
121 | | |
122 | 0 | PlatformMinVersion = OsVersion; |
123 | 0 | } |
124 | | |
125 | | static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts, |
126 | 0 | MacroBuilder &Builder) { |
127 | 0 | DefineStd(Builder, "WIN32", Opts); |
128 | 0 | DefineStd(Builder, "WINNT", Opts); |
129 | 0 | if (Triple.isArch64Bit()) { |
130 | 0 | DefineStd(Builder, "WIN64", Opts); |
131 | 0 | Builder.defineMacro("__MINGW64__"); |
132 | 0 | } |
133 | 0 | Builder.defineMacro("__MSVCRT__"); |
134 | 0 | Builder.defineMacro("__MINGW32__"); |
135 | 0 | addCygMingDefines(Opts, Builder); |
136 | 0 | } |
137 | | |
138 | 0 | static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { |
139 | 0 | if (Opts.CPlusPlus) { |
140 | 0 | if (Opts.RTTIData) |
141 | 0 | Builder.defineMacro("_CPPRTTI"); |
142 | |
|
143 | 0 | if (Opts.CXXExceptions) |
144 | 0 | Builder.defineMacro("_CPPUNWIND"); |
145 | 0 | } |
146 | |
|
147 | 0 | if (Opts.Bool) |
148 | 0 | Builder.defineMacro("__BOOL_DEFINED"); |
149 | |
|
150 | 0 | if (!Opts.CharIsSigned) |
151 | 0 | Builder.defineMacro("_CHAR_UNSIGNED"); |
152 | | |
153 | | // "The /fp:contract option allows the compiler to generate floating-point |
154 | | // contractions [...]" |
155 | 0 | if (Opts.getDefaultFPContractMode() != LangOptions::FPModeKind::FPM_Off) |
156 | 0 | 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 | 0 | if (Opts.getDefaultExceptionMode() == |
162 | 0 | LangOptions::FPExceptionModeKind::FPE_Strict) |
163 | 0 | 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 | 0 | const bool any_imprecise_flags = |
177 | 0 | Opts.FastMath || Opts.FiniteMathOnly || Opts.UnsafeFPMath || |
178 | 0 | Opts.AllowFPReassoc || Opts.NoHonorNaNs || Opts.NoHonorInfs || |
179 | 0 | 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 | 0 | if (Opts.getDefaultRoundingMode() == |
187 | 0 | LangOptions::RoundingMode::NearestTiesToEven) { |
188 | 0 | if (any_imprecise_flags) { |
189 | 0 | Builder.defineMacro("_M_FP_FAST"); |
190 | 0 | } else { |
191 | 0 | Builder.defineMacro("_M_FP_PRECISE"); |
192 | 0 | } |
193 | 0 | } else if (!any_imprecise_flags && Opts.getDefaultRoundingMode() == |
194 | 0 | 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 | 0 | Builder.defineMacro("_M_FP_STRICT"); |
199 | 0 | } |
200 | | |
201 | | // FIXME: POSIXThreads isn't exactly the option this should be defined for, |
202 | | // but it works for now. |
203 | 0 | if (Opts.POSIXThreads) |
204 | 0 | Builder.defineMacro("_MT"); |
205 | |
|
206 | 0 | if (Opts.MSCompatibilityVersion) { |
207 | 0 | Builder.defineMacro("_MSC_VER", |
208 | 0 | Twine(Opts.MSCompatibilityVersion / 100000)); |
209 | 0 | Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); |
210 | | // FIXME We cannot encode the revision information into 32-bits |
211 | 0 | Builder.defineMacro("_MSC_BUILD", Twine(1)); |
212 | |
|
213 | 0 | if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) |
214 | 0 | Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); |
215 | |
|
216 | 0 | if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { |
217 | 0 | if (Opts.CPlusPlus23) |
218 | | // TODO update to the proper value. |
219 | 0 | Builder.defineMacro("_MSVC_LANG", "202004L"); |
220 | 0 | else if (Opts.CPlusPlus20) |
221 | 0 | Builder.defineMacro("_MSVC_LANG", "202002L"); |
222 | 0 | else if (Opts.CPlusPlus17) |
223 | 0 | Builder.defineMacro("_MSVC_LANG", "201703L"); |
224 | 0 | else if (Opts.CPlusPlus14) |
225 | 0 | Builder.defineMacro("_MSVC_LANG", "201402L"); |
226 | 0 | } |
227 | |
|
228 | 0 | if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2022_3)) |
229 | 0 | Builder.defineMacro("_MSVC_CONSTEXPR_ATTRIBUTE"); |
230 | 0 | } |
231 | |
|
232 | 0 | if (Opts.MicrosoftExt) { |
233 | 0 | Builder.defineMacro("_MSC_EXTENSIONS"); |
234 | |
|
235 | 0 | if (Opts.CPlusPlus11) { |
236 | 0 | Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED"); |
237 | 0 | Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED"); |
238 | 0 | Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED"); |
239 | 0 | } |
240 | 0 | } |
241 | |
|
242 | 0 | if (!Opts.MSVolatile) |
243 | 0 | Builder.defineMacro("_ISO_VOLATILE"); |
244 | |
|
245 | 0 | if (Opts.Kernel) |
246 | 0 | Builder.defineMacro("_KERNEL_MODE"); |
247 | |
|
248 | 0 | Builder.defineMacro("_INTEGRAL_MAX_BITS", "64"); |
249 | 0 | Builder.defineMacro("__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 | 0 | Builder.defineMacro("_MSVC_EXECUTION_CHARACTER_SET", "65001"); |
258 | 0 | } |
259 | | |
260 | | void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, |
261 | 0 | MacroBuilder &Builder) { |
262 | 0 | Builder.defineMacro("_WIN32"); |
263 | 0 | if (Triple.isArch64Bit()) |
264 | 0 | Builder.defineMacro("_WIN64"); |
265 | 0 | if (Triple.isWindowsGNUEnvironment()) |
266 | 0 | addMinGWDefines(Triple, Opts, Builder); |
267 | 0 | else if (Triple.isKnownWindowsMSVCEnvironment() || |
268 | 0 | (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat)) |
269 | 0 | addVisualCDefines(Opts, Builder); |
270 | 0 | } |
271 | | |
272 | | } // namespace targets |
273 | | } // namespace clang |