1326941Sdim//===--- OSTargets.cpp - Implement OS target feature support --------------===//
2326941Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326941Sdim//
7326941Sdim//===----------------------------------------------------------------------===//
8326941Sdim//
9326941Sdim// This file implements OS specific TargetInfo types.
10326941Sdim//===----------------------------------------------------------------------===//
11326941Sdim
12326941Sdim#include "OSTargets.h"
13326941Sdim#include "clang/Basic/MacroBuilder.h"
14326941Sdim#include "llvm/ADT/StringRef.h"
15326941Sdim
16326941Sdimusing namespace clang;
17326941Sdimusing namespace clang::targets;
18326941Sdim
19326941Sdimnamespace clang {
20326941Sdimnamespace targets {
21326941Sdim
22326941Sdimvoid getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
23326941Sdim                      const llvm::Triple &Triple, StringRef &PlatformName,
24326941Sdim                      VersionTuple &PlatformMinVersion) {
25326941Sdim  Builder.defineMacro("__APPLE_CC__", "6000");
26326941Sdim  Builder.defineMacro("__APPLE__");
27326941Sdim  Builder.defineMacro("__STDC_NO_THREADS__");
28326941Sdim  Builder.defineMacro("OBJC_NEW_PROPERTIES");
29326941Sdim  // AddressSanitizer doesn't play well with source fortification, which is on
30326941Sdim  // by default on Darwin.
31326941Sdim  if (Opts.Sanitize.has(SanitizerKind::Address))
32326941Sdim    Builder.defineMacro("_FORTIFY_SOURCE", "0");
33326941Sdim
34326941Sdim  // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
35344779Sdim  if (!Opts.ObjC) {
36326941Sdim    // __weak is always defined, for use in blocks and with objc pointers.
37326941Sdim    Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
38326941Sdim    Builder.defineMacro("__strong", "");
39326941Sdim    Builder.defineMacro("__unsafe_unretained", "");
40326941Sdim  }
41326941Sdim
42326941Sdim  if (Opts.Static)
43326941Sdim    Builder.defineMacro("__STATIC__");
44326941Sdim  else
45326941Sdim    Builder.defineMacro("__DYNAMIC__");
46326941Sdim
47326941Sdim  if (Opts.POSIXThreads)
48326941Sdim    Builder.defineMacro("_REENTRANT");
49326941Sdim
50326941Sdim  // Get the platform type and version number from the triple.
51326941Sdim  unsigned Maj, Min, Rev;
52326941Sdim  if (Triple.isMacOSX()) {
53326941Sdim    Triple.getMacOSXVersion(Maj, Min, Rev);
54326941Sdim    PlatformName = "macos";
55326941Sdim  } else {
56326941Sdim    Triple.getOSVersion(Maj, Min, Rev);
57326941Sdim    PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
58326941Sdim  }
59326941Sdim
60326941Sdim  // If -target arch-pc-win32-macho option specified, we're
61326941Sdim  // generating code for Win32 ABI. No need to emit
62326941Sdim  // __ENVIRONMENT_XX_OS_VERSION_MIN_REQUIRED__.
63326941Sdim  if (PlatformName == "win32") {
64326941Sdim    PlatformMinVersion = VersionTuple(Maj, Min, Rev);
65326941Sdim    return;
66326941Sdim  }
67326941Sdim
68326941Sdim  // Set the appropriate OS version define.
69326941Sdim  if (Triple.isiOS()) {
70326941Sdim    assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
71326941Sdim    char Str[7];
72326941Sdim    if (Maj < 10) {
73326941Sdim      Str[0] = '0' + Maj;
74326941Sdim      Str[1] = '0' + (Min / 10);
75326941Sdim      Str[2] = '0' + (Min % 10);
76326941Sdim      Str[3] = '0' + (Rev / 10);
77326941Sdim      Str[4] = '0' + (Rev % 10);
78326941Sdim      Str[5] = '\0';
79326941Sdim    } else {
80326941Sdim      // Handle versions >= 10.
81326941Sdim      Str[0] = '0' + (Maj / 10);
82326941Sdim      Str[1] = '0' + (Maj % 10);
83326941Sdim      Str[2] = '0' + (Min / 10);
84326941Sdim      Str[3] = '0' + (Min % 10);
85326941Sdim      Str[4] = '0' + (Rev / 10);
86326941Sdim      Str[5] = '0' + (Rev % 10);
87326941Sdim      Str[6] = '\0';
88326941Sdim    }
89326941Sdim    if (Triple.isTvOS())
90326941Sdim      Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
91326941Sdim    else
92326941Sdim      Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
93326941Sdim                          Str);
94326941Sdim
95326941Sdim  } else if (Triple.isWatchOS()) {
96326941Sdim    assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
97326941Sdim    char Str[6];
98326941Sdim    Str[0] = '0' + Maj;
99326941Sdim    Str[1] = '0' + (Min / 10);
100326941Sdim    Str[2] = '0' + (Min % 10);
101326941Sdim    Str[3] = '0' + (Rev / 10);
102326941Sdim    Str[4] = '0' + (Rev % 10);
103326941Sdim    Str[5] = '\0';
104326941Sdim    Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
105326941Sdim  } else if (Triple.isMacOSX()) {
106326941Sdim    // Note that the Driver allows versions which aren't representable in the
107326941Sdim    // define (because we only get a single digit for the minor and micro
108326941Sdim    // revision numbers). So, we limit them to the maximum representable
109326941Sdim    // version.
110326941Sdim    assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!");
111326941Sdim    char Str[7];
112326941Sdim    if (Maj < 10 || (Maj == 10 && Min < 10)) {
113326941Sdim      Str[0] = '0' + (Maj / 10);
114326941Sdim      Str[1] = '0' + (Maj % 10);
115326941Sdim      Str[2] = '0' + std::min(Min, 9U);
116326941Sdim      Str[3] = '0' + std::min(Rev, 9U);
117326941Sdim      Str[4] = '\0';
118326941Sdim    } else {
119326941Sdim      // Handle versions > 10.9.
120326941Sdim      Str[0] = '0' + (Maj / 10);
121326941Sdim      Str[1] = '0' + (Maj % 10);
122326941Sdim      Str[2] = '0' + (Min / 10);
123326941Sdim      Str[3] = '0' + (Min % 10);
124326941Sdim      Str[4] = '0' + (Rev / 10);
125326941Sdim      Str[5] = '0' + (Rev % 10);
126326941Sdim      Str[6] = '\0';
127326941Sdim    }
128326941Sdim    Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
129326941Sdim  }
130326941Sdim
131326941Sdim  // Tell users about the kernel if there is one.
132326941Sdim  if (Triple.isOSDarwin())
133326941Sdim    Builder.defineMacro("__MACH__");
134326941Sdim
135326941Sdim  PlatformMinVersion = VersionTuple(Maj, Min, Rev);
136326941Sdim}
137353358Sdim
138353358Sdimstatic void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
139353358Sdim                            MacroBuilder &Builder) {
140353358Sdim  DefineStd(Builder, "WIN32", Opts);
141353358Sdim  DefineStd(Builder, "WINNT", Opts);
142353358Sdim  if (Triple.isArch64Bit()) {
143353358Sdim    DefineStd(Builder, "WIN64", Opts);
144353358Sdim    Builder.defineMacro("__MINGW64__");
145353358Sdim  }
146353358Sdim  Builder.defineMacro("__MSVCRT__");
147353358Sdim  Builder.defineMacro("__MINGW32__");
148353358Sdim  addCygMingDefines(Opts, Builder);
149353358Sdim}
150353358Sdim
151353358Sdimstatic void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
152353358Sdim  if (Opts.CPlusPlus) {
153353358Sdim    if (Opts.RTTIData)
154353358Sdim      Builder.defineMacro("_CPPRTTI");
155353358Sdim
156353358Sdim    if (Opts.CXXExceptions)
157353358Sdim      Builder.defineMacro("_CPPUNWIND");
158353358Sdim  }
159353358Sdim
160353358Sdim  if (Opts.Bool)
161353358Sdim    Builder.defineMacro("__BOOL_DEFINED");
162353358Sdim
163353358Sdim  if (!Opts.CharIsSigned)
164353358Sdim    Builder.defineMacro("_CHAR_UNSIGNED");
165353358Sdim
166353358Sdim  // FIXME: POSIXThreads isn't exactly the option this should be defined for,
167353358Sdim  //        but it works for now.
168353358Sdim  if (Opts.POSIXThreads)
169353358Sdim    Builder.defineMacro("_MT");
170353358Sdim
171353358Sdim  if (Opts.MSCompatibilityVersion) {
172353358Sdim    Builder.defineMacro("_MSC_VER",
173353358Sdim                        Twine(Opts.MSCompatibilityVersion / 100000));
174353358Sdim    Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
175353358Sdim    // FIXME We cannot encode the revision information into 32-bits
176353358Sdim    Builder.defineMacro("_MSC_BUILD", Twine(1));
177353358Sdim
178353358Sdim    if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
179353358Sdim      Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
180353358Sdim
181353358Sdim    if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
182353358Sdim      if (Opts.CPlusPlus2a)
183360784Sdim        Builder.defineMacro("_MSVC_LANG", "201705L");
184353358Sdim      else if (Opts.CPlusPlus17)
185353358Sdim        Builder.defineMacro("_MSVC_LANG", "201703L");
186353358Sdim      else if (Opts.CPlusPlus14)
187353358Sdim        Builder.defineMacro("_MSVC_LANG", "201402L");
188353358Sdim    }
189353358Sdim  }
190353358Sdim
191353358Sdim  if (Opts.MicrosoftExt) {
192353358Sdim    Builder.defineMacro("_MSC_EXTENSIONS");
193353358Sdim
194353358Sdim    if (Opts.CPlusPlus11) {
195353358Sdim      Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
196353358Sdim      Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
197353358Sdim      Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
198353358Sdim    }
199353358Sdim  }
200353358Sdim
201353358Sdim  Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
202353358Sdim}
203353358Sdim
204353358Sdimvoid addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
205353358Sdim                       MacroBuilder &Builder) {
206353358Sdim  Builder.defineMacro("_WIN32");
207353358Sdim  if (Triple.isArch64Bit())
208353358Sdim    Builder.defineMacro("_WIN64");
209353358Sdim  if (Triple.isWindowsGNUEnvironment())
210353358Sdim    addMinGWDefines(Triple, Opts, Builder);
211353358Sdim  else if (Triple.isKnownWindowsMSVCEnvironment() ||
212353358Sdim           (Triple.isWindowsItaniumEnvironment() && Opts.MSVCCompat))
213353358Sdim    addVisualCDefines(Opts, Builder);
214353358Sdim}
215353358Sdim
216326941Sdim} // namespace targets
217326941Sdim} // namespace clang
218