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
16using namespace clang;
17using namespace clang::targets;
18
19namespace clang {
20namespace targets {
21
22void 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
56void 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
136static 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
149static 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
277void 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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Basic/Targets/OSTargets.cpp