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 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  Builder.defineMacro("OBJC_NEW_PROPERTIES");
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  unsigned Maj, Min, Rev;
52  if (Triple.isMacOSX()) {
53    Triple.getMacOSXVersion(Maj, Min, Rev);
54    PlatformName = "macos";
55  } else {
56    Triple.getOSVersion(Maj, Min, Rev);
57    PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
58  }
59
60  // If -target arch-pc-win32-macho option specified, we're
61  // generating code for Win32 ABI. No need to emit
62  // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__.
63  if (PlatformName == "win32") {
64    PlatformMinVersion = VersionTuple(Maj, Min, Rev);
65    return;
66  }
67
68  // Set the appropriate OS version define.
69  if (Triple.isiOS()) {
70    assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
71    char Str[7];
72    if (Maj < 10) {
73      Str[0] = '0' + Maj;
74      Str[1] = '0' + (Min / 10);
75      Str[2] = '0' + (Min % 10);
76      Str[3] = '0' + (Rev / 10);
77      Str[4] = '0' + (Rev % 10);
78      Str[5] = '\0';
79    } else {
80      // Handle versions >= 10.
81      Str[0] = '0' + (Maj / 10);
82      Str[1] = '0' + (Maj % 10);
83      Str[2] = '0' + (Min / 10);
84      Str[3] = '0' + (Min % 10);
85      Str[4] = '0' + (Rev / 10);
86      Str[5] = '0' + (Rev % 10);
87      Str[6] = '\0';
88    }
89    if (Triple.isTvOS())
90      Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
91    else
92      Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
93                          Str);
94
95  } else if (Triple.isWatchOS()) {
96    assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
97    char Str[6];
98    Str[0] = '0' + Maj;
99    Str[1] = '0' + (Min / 10);
100    Str[2] = '0' + (Min % 10);
101    Str[3] = '0' + (Rev / 10);
102    Str[4] = '0' + (Rev % 10);
103    Str[5] = '\0';
104    Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
105  } else if (Triple.isMacOSX()) {
106    // Note that the Driver allows versions which aren't representable in the
107    // define (because we only get a single digit for the minor and micro
108    // revision numbers). So, we limit them to the maximum representable
109    // version.
110    assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
111    char Str[7];
112    if (Maj < 10 || (Maj == 10 && Min < 10)) {
113      Str[0] = '0' + (Maj / 10);
114      Str[1] = '0' + (Maj % 10);
115      Str[2] = '0' + std::min(Min, 9U);
116      Str[3] = '0' + std::min(Rev, 9U);
117      Str[4] = '\0';
118    } else {
119      // Handle versions > 10.9.
120      Str[0] = '0' + (Maj / 10);
121      Str[1] = '0' + (Maj % 10);
122      Str[2] = '0' + (Min / 10);
123      Str[3] = '0' + (Min % 10);
124      Str[4] = '0' + (Rev / 10);
125      Str[5] = '0' + (Rev % 10);
126      Str[6] = '\0';
127    }
128    Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
129  }
130
131  // Tell users about the kernel if there is one.
132  if (Triple.isOSDarwin())
133    Builder.defineMacro("__MACH__");
134
135  PlatformMinVersion = VersionTuple(Maj, Min, Rev);
136}
137
138static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
139                            MacroBuilder &Builder) {
140  DefineStd(Builder, "WIN32", Opts);
141  DefineStd(Builder, "WINNT", Opts);
142  if (Triple.isArch64Bit()) {
143    DefineStd(Builder, "WIN64", Opts);
144    Builder.defineMacro("__MINGW64__");
145  }
146  Builder.defineMacro("__MSVCRT__");
147  Builder.defineMacro("__MINGW32__");
148  addCygMingDefines(Opts, Builder);
149}
150
151static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
152  if (Opts.CPlusPlus) {
153    if (Opts.RTTIData)
154      Builder.defineMacro("_CPPRTTI");
155
156    if (Opts.CXXExceptions)
157      Builder.defineMacro("_CPPUNWIND");
158  }
159
160  if (Opts.Bool)
161    Builder.defineMacro("__BOOL_DEFINED");
162
163  if (!Opts.CharIsSigned)
164    Builder.defineMacro("_CHAR_UNSIGNED");
165
166  // FIXME: POSIXThreads isn't exactly the option this should be defined for,
167  //        but it works for now.
168  if (Opts.POSIXThreads)
169    Builder.defineMacro("_MT");
170
171  if (Opts.MSCompatibilityVersion) {
172    Builder.defineMacro("_MSC_VER",
173                        Twine(Opts.MSCompatibilityVersion / 100000));
174    Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
175    // FIXME We cannot encode the revision information into 32-bits
176    Builder.defineMacro("_MSC_BUILD", Twine(1));
177
178    if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
179      Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
180
181    if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
182      if (Opts.CPlusPlus2a)
183        Builder.defineMacro("_MSVC_LANG", "201705L");
184      else if (Opts.CPlusPlus17)
185        Builder.defineMacro("_MSVC_LANG", "201703L");
186      else if (Opts.CPlusPlus14)
187        Builder.defineMacro("_MSVC_LANG", "201402L");
188    }
189  }
190
191  if (Opts.MicrosoftExt) {
192    Builder.defineMacro("_MSC_EXTENSIONS");
193
194    if (Opts.CPlusPlus11) {
195      Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
196      Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
197      Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
198    }
199  }
200
201  Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
202}
203
204void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
205                       MacroBuilder &Builder) {
206  Builder.defineMacro("_WIN32");
207  if (Triple.isArch64Bit())
208    Builder.defineMacro("_WIN64");
209  if (Triple.isWindowsGNUEnvironment())
210    addMinGWDefines(Triple, Opts, Builder);
211  else if (Triple.isKnownWindowsMSVCEnvironment() ||
212           (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat))
213    addVisualCDefines(Opts, Builder);
214}
215
216} // namespace targets
217} // namespace clang
218