1//===--- OSTargets.h - Declare OS target feature support --------*- C++ -*-===//
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 declares OS specific TargetInfo types.
10//===----------------------------------------------------------------------===//
11
12#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
13#define LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
14
15#include "Targets.h"
16
17namespace clang {
18namespace targets {
19
20template <typename TgtInfo>
21class LLVM_LIBRARY_VISIBILITY OSTargetInfo : public TgtInfo {
22protected:
23  virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
24                            MacroBuilder &Builder) const = 0;
25
26public:
27  OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
28      : TgtInfo(Triple, Opts) {}
29
30  void getTargetDefines(const LangOptions &Opts,
31                        MacroBuilder &Builder) const override {
32    TgtInfo::getTargetDefines(Opts, Builder);
33    getOSDefines(Opts, TgtInfo::getTriple(), Builder);
34  }
35};
36
37void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
38                      const llvm::Triple &Triple, StringRef &PlatformName,
39                      VersionTuple &PlatformMinVersion);
40
41template <typename Target>
42class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo : public OSTargetInfo<Target> {
43protected:
44  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
45                    MacroBuilder &Builder) const override {
46    getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
47                     this->PlatformMinVersion);
48  }
49
50public:
51  DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
52      : OSTargetInfo<Target>(Triple, Opts) {
53    // By default, no TLS, and we list permitted architecture/OS
54    // combinations.
55    this->TLSSupported = false;
56
57    if (Triple.isMacOSX())
58      this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
59    else if (Triple.isiOS()) {
60      // 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards,
61      // 32-bit simulator from 10 onwards.
62      if (Triple.isArch64Bit())
63        this->TLSSupported = !Triple.isOSVersionLT(8);
64      else if (Triple.isArch32Bit()) {
65        if (!Triple.isSimulatorEnvironment())
66          this->TLSSupported = !Triple.isOSVersionLT(9);
67        else
68          this->TLSSupported = !Triple.isOSVersionLT(10);
69      }
70    } else if (Triple.isWatchOS()) {
71      if (!Triple.isSimulatorEnvironment())
72        this->TLSSupported = !Triple.isOSVersionLT(2);
73      else
74        this->TLSSupported = !Triple.isOSVersionLT(3);
75    } else if (Triple.isDriverKit()) {
76      // No TLS on DriverKit.
77    } else if (Triple.isXROS())
78      this->TLSSupported = true;
79
80    this->MCountName = "\01mcount";
81  }
82
83  const char *getStaticInitSectionSpecifier() const override {
84    // FIXME: We should return 0 when building kexts.
85    return "__TEXT,__StaticInit,regular,pure_instructions";
86  }
87
88  /// Darwin does not support protected visibility.  Darwin's "default"
89  /// is very similar to ELF's "protected";  Darwin requires a "weak"
90  /// attribute on declarations that can be dynamically replaced.
91  bool hasProtectedVisibility() const override { return false; }
92
93  unsigned getExnObjectAlignment() const override {
94    // Older versions of libc++abi guarantee an alignment of only 8-bytes for
95    // exception objects because of a bug in __cxa_exception that was
96    // eventually fixed in r319123.
97    llvm::VersionTuple MinVersion;
98    const llvm::Triple &T = this->getTriple();
99
100    // Compute the earliest OS versions that have the fix to libc++abi.
101    switch (T.getOS()) {
102    case llvm::Triple::Darwin:
103    case llvm::Triple::MacOSX: // Earliest supporting version is 10.14.
104      MinVersion = llvm::VersionTuple(10U, 14U);
105      break;
106    case llvm::Triple::IOS:
107    case llvm::Triple::TvOS: // Earliest supporting version is 12.0.0.
108      MinVersion = llvm::VersionTuple(12U);
109      break;
110    case llvm::Triple::WatchOS: // Earliest supporting version is 5.0.0.
111      MinVersion = llvm::VersionTuple(5U);
112      break;
113    case llvm::Triple::XROS:
114      MinVersion = llvm::VersionTuple(0);
115      break;
116    default:
117      // Conservatively return 8 bytes if OS is unknown.
118      return 64;
119    }
120
121    if (T.getOSVersion() < MinVersion)
122      return 64;
123    return OSTargetInfo<Target>::getExnObjectAlignment();
124  }
125
126  TargetInfo::IntType getLeastIntTypeByWidth(unsigned BitWidth,
127                                             bool IsSigned) const final {
128    // Darwin uses `long long` for `int_least64_t` and `int_fast64_t`.
129    return BitWidth == 64
130               ? (IsSigned ? TargetInfo::SignedLongLong
131                           : TargetInfo::UnsignedLongLong)
132               : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
133  }
134
135  bool areDefaultedSMFStillPOD(const LangOptions &) const override {
136    return false;
137  }
138};
139
140// DragonFlyBSD Target
141template <typename Target>
142class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
143    : public OSTargetInfo<Target> {
144protected:
145  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
146                    MacroBuilder &Builder) const override {
147    // DragonFly defines; list based off of gcc output
148    Builder.defineMacro("__DragonFly__");
149    Builder.defineMacro("__DragonFly_cc_version", "100001");
150    Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
151    Builder.defineMacro("__tune_i386__");
152    DefineStd(Builder, "unix", Opts);
153    if (this->HasFloat128)
154      Builder.defineMacro("__FLOAT128__");
155  }
156
157public:
158  DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
159      : OSTargetInfo<Target>(Triple, Opts) {
160    switch (Triple.getArch()) {
161    default:
162    case llvm::Triple::x86:
163    case llvm::Triple::x86_64:
164      this->HasFloat128 = true;
165      this->MCountName = ".mcount";
166      break;
167    }
168  }
169};
170
171#ifndef FREEBSD_CC_VERSION
172#define FREEBSD_CC_VERSION 0U
173#endif
174
175// FreeBSD Target
176template <typename Target>
177class LLVM_LIBRARY_VISIBILITY FreeBSDTargetInfo : public OSTargetInfo<Target> {
178protected:
179  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
180                    MacroBuilder &Builder) const override {
181    // FreeBSD defines; list based off of gcc output
182
183    unsigned Release = Triple.getOSMajorVersion();
184    if (Release == 0U)
185      Release = 8U;
186    unsigned CCVersion = FREEBSD_CC_VERSION;
187    if (CCVersion == 0U)
188      CCVersion = Release * 100000U + 1U;
189
190    Builder.defineMacro("__FreeBSD__", Twine(Release));
191    Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion));
192    Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
193    DefineStd(Builder, "unix", Opts);
194    if (this->HasFloat128)
195      Builder.defineMacro("__FLOAT128__");
196
197    // On FreeBSD, wchar_t contains the number of the code point as
198    // used by the character set of the locale. These character sets are
199    // not necessarily a superset of ASCII.
200    //
201    // FIXME: This is wrong; the macro refers to the numerical values
202    // of wchar_t *literals*, which are not locale-dependent. However,
203    // FreeBSD systems apparently depend on us getting this wrong, and
204    // setting this to 1 is conforming even if all the basic source
205    // character literals have the same encoding as char and wchar_t.
206    Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1");
207  }
208
209public:
210  FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
211      : OSTargetInfo<Target>(Triple, Opts) {
212    switch (Triple.getArch()) {
213    case llvm::Triple::x86:
214    case llvm::Triple::x86_64:
215      this->HasFloat128 = true;
216      [[fallthrough]];
217    default:
218      this->MCountName = ".mcount";
219      break;
220    case llvm::Triple::mips:
221    case llvm::Triple::mipsel:
222    case llvm::Triple::ppc:
223    case llvm::Triple::ppcle:
224    case llvm::Triple::ppc64:
225    case llvm::Triple::ppc64le:
226      this->MCountName = "_mcount";
227      break;
228    case llvm::Triple::arm:
229      this->MCountName = "__mcount";
230      break;
231    case llvm::Triple::riscv32:
232    case llvm::Triple::riscv64:
233      break;
234    }
235  }
236};
237
238// GNU/kFreeBSD Target
239template <typename Target>
240class LLVM_LIBRARY_VISIBILITY KFreeBSDTargetInfo : public OSTargetInfo<Target> {
241protected:
242  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
243                    MacroBuilder &Builder) const override {
244    // GNU/kFreeBSD defines; list based off of gcc output
245
246    DefineStd(Builder, "unix", Opts);
247    Builder.defineMacro("__FreeBSD_kernel__");
248    Builder.defineMacro("__GLIBC__");
249    if (Opts.POSIXThreads)
250      Builder.defineMacro("_REENTRANT");
251    if (Opts.CPlusPlus)
252      Builder.defineMacro("_GNU_SOURCE");
253  }
254
255public:
256  using OSTargetInfo<Target>::OSTargetInfo;
257};
258
259// Haiku Target
260template <typename Target>
261class LLVM_LIBRARY_VISIBILITY HaikuTargetInfo : public OSTargetInfo<Target> {
262protected:
263  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
264                    MacroBuilder &Builder) const override {
265    // Haiku defines; list based off of gcc output
266    Builder.defineMacro("__HAIKU__");
267    DefineStd(Builder, "unix", Opts);
268    if (this->HasFloat128)
269      Builder.defineMacro("__FLOAT128__");
270  }
271
272public:
273  HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
274      : OSTargetInfo<Target>(Triple, Opts) {
275    this->SizeType = TargetInfo::UnsignedLong;
276    this->IntPtrType = TargetInfo::SignedLong;
277    this->PtrDiffType = TargetInfo::SignedLong;
278    this->ProcessIDType = TargetInfo::SignedLong;
279    switch (Triple.getArch()) {
280    default:
281      break;
282    case llvm::Triple::x86:
283    case llvm::Triple::x86_64:
284      this->HasFloat128 = true;
285      break;
286    }
287  }
288};
289
290// Hurd target
291template <typename Target>
292class LLVM_LIBRARY_VISIBILITY HurdTargetInfo : public OSTargetInfo<Target> {
293protected:
294  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
295                    MacroBuilder &Builder) const override {
296    // Hurd defines; list based off of gcc output.
297    DefineStd(Builder, "unix", Opts);
298    Builder.defineMacro("__GNU__");
299    Builder.defineMacro("__gnu_hurd__");
300    Builder.defineMacro("__MACH__");
301    Builder.defineMacro("__GLIBC__");
302    if (Opts.POSIXThreads)
303      Builder.defineMacro("_REENTRANT");
304    if (Opts.CPlusPlus)
305      Builder.defineMacro("_GNU_SOURCE");
306  }
307public:
308  using OSTargetInfo<Target>::OSTargetInfo;
309};
310
311// Linux target
312template <typename Target>
313class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
314protected:
315  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
316                    MacroBuilder &Builder) const override {
317    // Linux defines; list based off of gcc output
318    DefineStd(Builder, "unix", Opts);
319    DefineStd(Builder, "linux", Opts);
320    if (Triple.isAndroid()) {
321      Builder.defineMacro("__ANDROID__", "1");
322      this->PlatformName = "android";
323      this->PlatformMinVersion = Triple.getEnvironmentVersion();
324      const unsigned Maj = this->PlatformMinVersion.getMajor();
325      if (Maj) {
326        Builder.defineMacro("__ANDROID_MIN_SDK_VERSION__", Twine(Maj));
327        // This historical but ambiguous name for the minSdkVersion macro. Keep
328        // defined for compatibility.
329        Builder.defineMacro("__ANDROID_API__", "__ANDROID_MIN_SDK_VERSION__");
330      }
331    } else {
332        Builder.defineMacro("__gnu_linux__");
333    }
334    if (Opts.POSIXThreads)
335      Builder.defineMacro("_REENTRANT");
336    if (Opts.CPlusPlus)
337      Builder.defineMacro("_GNU_SOURCE");
338    if (this->HasFloat128)
339      Builder.defineMacro("__FLOAT128__");
340  }
341
342public:
343  LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
344      : OSTargetInfo<Target>(Triple, Opts) {
345    this->WIntType = TargetInfo::UnsignedInt;
346
347    switch (Triple.getArch()) {
348    default:
349      break;
350    case llvm::Triple::mips:
351    case llvm::Triple::mipsel:
352    case llvm::Triple::mips64:
353    case llvm::Triple::mips64el:
354    case llvm::Triple::ppc:
355    case llvm::Triple::ppcle:
356    case llvm::Triple::ppc64:
357    case llvm::Triple::ppc64le:
358      this->MCountName = "_mcount";
359      break;
360    case llvm::Triple::x86:
361    case llvm::Triple::x86_64:
362      this->HasFloat128 = true;
363      break;
364    }
365  }
366
367  const char *getStaticInitSectionSpecifier() const override {
368    return ".text.startup";
369  }
370};
371
372// NetBSD Target
373template <typename Target>
374class LLVM_LIBRARY_VISIBILITY NetBSDTargetInfo : public OSTargetInfo<Target> {
375protected:
376  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
377                    MacroBuilder &Builder) const override {
378    // NetBSD defines; list based off of gcc output
379    Builder.defineMacro("__NetBSD__");
380    Builder.defineMacro("__unix__");
381    if (Opts.POSIXThreads)
382      Builder.defineMacro("_REENTRANT");
383    if (this->HasFloat128)
384      Builder.defineMacro("__FLOAT128__");
385  }
386
387public:
388  NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
389      : OSTargetInfo<Target>(Triple, Opts) {
390    this->MCountName = "__mcount";
391    switch (Triple.getArch()) {
392    default:
393      break;
394    case llvm::Triple::x86:
395    case llvm::Triple::x86_64:
396      this->HasFloat128 = true;
397      break;
398    }
399  }
400};
401
402// OpenBSD Target
403template <typename Target>
404class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
405protected:
406  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
407                    MacroBuilder &Builder) const override {
408    // OpenBSD defines; list based off of gcc output
409
410    Builder.defineMacro("__OpenBSD__");
411    DefineStd(Builder, "unix", Opts);
412    if (Opts.POSIXThreads)
413      Builder.defineMacro("_REENTRANT");
414    if (this->HasFloat128)
415      Builder.defineMacro("__FLOAT128__");
416
417    if (Opts.C11)
418      Builder.defineMacro("__STDC_NO_THREADS__");
419  }
420
421public:
422  OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
423      : OSTargetInfo<Target>(Triple, Opts) {
424    this->WCharType = this->WIntType = this->SignedInt;
425    this->IntMaxType = TargetInfo::SignedLongLong;
426    this->Int64Type = TargetInfo::SignedLongLong;
427    switch (Triple.getArch()) {
428    case llvm::Triple::x86:
429    case llvm::Triple::x86_64:
430      this->HasFloat128 = true;
431      [[fallthrough]];
432    default:
433      this->MCountName = "__mcount";
434      break;
435    case llvm::Triple::mips64:
436    case llvm::Triple::mips64el:
437    case llvm::Triple::ppc:
438    case llvm::Triple::ppc64:
439    case llvm::Triple::ppc64le:
440    case llvm::Triple::sparcv9:
441      this->MCountName = "_mcount";
442      break;
443    case llvm::Triple::riscv32:
444    case llvm::Triple::riscv64:
445      break;
446    }
447  }
448};
449
450// PS3 PPU Target
451template <typename Target>
452class LLVM_LIBRARY_VISIBILITY PS3PPUTargetInfo : public OSTargetInfo<Target> {
453protected:
454  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
455                    MacroBuilder &Builder) const override {
456    // PS3 PPU defines.
457    Builder.defineMacro("__PPU__");
458    Builder.defineMacro("__CELLOS_LV2__");
459    Builder.defineMacro("__LP32__");
460    Builder.defineMacro("_ARCH_PPC64");
461    Builder.defineMacro("__powerpc64__");
462  }
463
464public:
465  PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
466      : OSTargetInfo<Target>(Triple, Opts) {
467    this->LongWidth = this->LongAlign = 32;
468    this->PointerWidth = this->PointerAlign = 32;
469    this->IntMaxType = TargetInfo::SignedLongLong;
470    this->Int64Type = TargetInfo::SignedLongLong;
471    this->SizeType = TargetInfo::UnsignedInt;
472    this->resetDataLayout("E-m:e-p:32:32-Fi64-i64:64-n32:64");
473  }
474};
475
476// Common base class for PS4/PS5 targets.
477template <typename Target>
478class LLVM_LIBRARY_VISIBILITY PSOSTargetInfo : public OSTargetInfo<Target> {
479protected:
480  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
481                    MacroBuilder &Builder) const override {
482    Builder.defineMacro("__FreeBSD__", "9");
483    Builder.defineMacro("__FreeBSD_cc_version", "900001");
484    Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
485    DefineStd(Builder, "unix", Opts);
486    Builder.defineMacro("__SCE__");
487    Builder.defineMacro("__STDC_NO_COMPLEX__");
488    Builder.defineMacro("__STDC_NO_THREADS__");
489  }
490
491public:
492  PSOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
493      : OSTargetInfo<Target>(Triple, Opts) {
494    this->WCharType = TargetInfo::UnsignedShort;
495
496    // On PS4/PS5, TLS variable cannot be aligned to more than 32 bytes (256
497    // bits).
498    this->MaxTLSAlign = 256;
499
500    // On PS4/PS5, do not honor explicit bit field alignment,
501    // as in "__attribute__((aligned(2))) int b : 1;".
502    this->UseExplicitBitFieldAlignment = false;
503
504    this->MCountName = ".mcount";
505    this->NewAlign = 256;
506    this->SuitableAlign = 256;
507  }
508
509  TargetInfo::CallingConvCheckResult
510  checkCallingConvention(CallingConv CC) const override {
511    return (CC == CC_C) ? TargetInfo::CCCR_OK : TargetInfo::CCCR_Error;
512  }
513
514  bool areDefaultedSMFStillPOD(const LangOptions &) const override {
515    return false;
516  }
517};
518
519// PS4 Target
520template <typename Target>
521class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public PSOSTargetInfo<Target> {
522protected:
523  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
524                    MacroBuilder &Builder) const override {
525    // Start with base class defines.
526    PSOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
527
528    Builder.defineMacro("__ORBIS__");
529  }
530
531public:
532  using PSOSTargetInfo<Target>::PSOSTargetInfo;
533};
534
535// PS5 Target
536template <typename Target>
537class LLVM_LIBRARY_VISIBILITY PS5OSTargetInfo : public PSOSTargetInfo<Target> {
538protected:
539  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
540                    MacroBuilder &Builder) const override {
541    // Start with base class defines.
542    PSOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
543
544    Builder.defineMacro("__PROSPERO__");
545  }
546
547public:
548  using PSOSTargetInfo<Target>::PSOSTargetInfo;
549};
550
551// RTEMS Target
552template <typename Target>
553class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo<Target> {
554protected:
555  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
556                    MacroBuilder &Builder) const override {
557    // RTEMS defines; list based off of gcc output
558
559    Builder.defineMacro("__rtems__");
560    if (Opts.CPlusPlus)
561      Builder.defineMacro("_GNU_SOURCE");
562  }
563
564public:
565  RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
566      : OSTargetInfo<Target>(Triple, Opts) {
567    switch (Triple.getArch()) {
568    default:
569    case llvm::Triple::x86:
570      // this->MCountName = ".mcount";
571      break;
572    case llvm::Triple::mips:
573    case llvm::Triple::mipsel:
574    case llvm::Triple::ppc:
575    case llvm::Triple::ppc64:
576    case llvm::Triple::ppc64le:
577      // this->MCountName = "_mcount";
578      break;
579    case llvm::Triple::arm:
580      // this->MCountName = "__mcount";
581      break;
582    }
583  }
584};
585
586// Solaris target
587template <typename Target>
588class LLVM_LIBRARY_VISIBILITY SolarisTargetInfo : public OSTargetInfo<Target> {
589protected:
590  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
591                    MacroBuilder &Builder) const override {
592    DefineStd(Builder, "sun", Opts);
593    DefineStd(Builder, "unix", Opts);
594    Builder.defineMacro("__svr4__");
595    Builder.defineMacro("__SVR4");
596    // Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and
597    // newer, but to 500 for everything else.  feature_test.h has a check to
598    // ensure that you are not using C99 with an old version of X/Open or C89
599    // with a new version.
600    if (Opts.C99)
601      Builder.defineMacro("_XOPEN_SOURCE", "600");
602    else
603      Builder.defineMacro("_XOPEN_SOURCE", "500");
604    if (Opts.CPlusPlus) {
605      Builder.defineMacro("__C99FEATURES__");
606      Builder.defineMacro("_FILE_OFFSET_BITS", "64");
607    }
608    // GCC restricts the next two to C++.
609    Builder.defineMacro("_LARGEFILE_SOURCE");
610    Builder.defineMacro("_LARGEFILE64_SOURCE");
611    Builder.defineMacro("__EXTENSIONS__");
612    if (Opts.POSIXThreads)
613      Builder.defineMacro("_REENTRANT");
614    if (this->HasFloat128)
615      Builder.defineMacro("__FLOAT128__");
616  }
617
618public:
619  SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
620      : OSTargetInfo<Target>(Triple, Opts) {
621    if (this->PointerWidth == 64) {
622      this->WCharType = this->WIntType = this->SignedInt;
623    } else {
624      this->WCharType = this->WIntType = this->SignedLong;
625    }
626    switch (Triple.getArch()) {
627    default:
628      break;
629    case llvm::Triple::x86:
630    case llvm::Triple::x86_64:
631      this->HasFloat128 = true;
632      break;
633    }
634  }
635};
636
637// AIX Target
638template <typename Target>
639class AIXTargetInfo : public OSTargetInfo<Target> {
640protected:
641  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
642                    MacroBuilder &Builder) const override {
643    DefineStd(Builder, "unix", Opts);
644    Builder.defineMacro("_IBMR2");
645    Builder.defineMacro("_POWER");
646    Builder.defineMacro("__THW_BIG_ENDIAN__");
647
648    Builder.defineMacro("_AIX");
649    Builder.defineMacro("__TOS_AIX__");
650    Builder.defineMacro("__HOS_AIX__");
651
652    if (Opts.C11) {
653      Builder.defineMacro("__STDC_NO_ATOMICS__");
654      Builder.defineMacro("__STDC_NO_THREADS__");
655    }
656
657    if (Opts.EnableAIXExtendedAltivecABI)
658      Builder.defineMacro("__EXTABI__");
659
660    VersionTuple OsVersion = Triple.getOSVersion();
661
662    // Define AIX OS-Version Macros.
663    // Includes logic for legacy versions of AIX; no specific intent to support.
664    if (OsVersion >= VersionTuple(3, 2))
665      Builder.defineMacro("_AIX32");
666    if (OsVersion >= VersionTuple(4, 1))
667      Builder.defineMacro("_AIX41");
668    if (OsVersion >= VersionTuple(4, 3))
669      Builder.defineMacro("_AIX43");
670    if (OsVersion >= VersionTuple(5, 0))
671      Builder.defineMacro("_AIX50");
672    if (OsVersion >= VersionTuple(5, 1))
673      Builder.defineMacro("_AIX51");
674    if (OsVersion >= VersionTuple(5, 2))
675      Builder.defineMacro("_AIX52");
676    if (OsVersion >= VersionTuple(5, 3))
677      Builder.defineMacro("_AIX53");
678    if (OsVersion >= VersionTuple(6, 1))
679      Builder.defineMacro("_AIX61");
680    if (OsVersion >= VersionTuple(7, 1))
681      Builder.defineMacro("_AIX71");
682    if (OsVersion >= VersionTuple(7, 2))
683      Builder.defineMacro("_AIX72");
684    if (OsVersion >= VersionTuple(7, 3))
685      Builder.defineMacro("_AIX73");
686
687    // FIXME: Do not define _LONG_LONG when -fno-long-long is specified.
688    Builder.defineMacro("_LONG_LONG");
689
690    if (Opts.POSIXThreads) {
691      Builder.defineMacro("_THREAD_SAFE");
692    }
693
694    if (this->PointerWidth == 64) {
695      Builder.defineMacro("__64BIT__");
696    }
697
698    // Define _WCHAR_T when it is a fundamental type
699    // (i.e., for C++ without -fno-wchar).
700    if (Opts.CPlusPlus && Opts.WChar) {
701      Builder.defineMacro("_WCHAR_T");
702    }
703  }
704
705public:
706  AIXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
707      : OSTargetInfo<Target>(Triple, Opts) {
708    this->MCountName = "__mcount";
709    this->TheCXXABI.set(TargetCXXABI::XL);
710
711    if (this->PointerWidth == 64) {
712      this->WCharType = this->UnsignedInt;
713    } else {
714      this->WCharType = this->UnsignedShort;
715    }
716    this->UseZeroLengthBitfieldAlignment = true;
717  }
718
719  // AIX sets FLT_EVAL_METHOD to be 1.
720  LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
721    return LangOptions::FPEvalMethodKind::FEM_Double;
722  }
723
724  bool defaultsToAIXPowerAlignment() const override { return true; }
725
726  bool areDefaultedSMFStillPOD(const LangOptions &) const override {
727    return false;
728  }
729};
730
731// z/OS target
732template <typename Target>
733class LLVM_LIBRARY_VISIBILITY ZOSTargetInfo : public OSTargetInfo<Target> {
734protected:
735  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
736                    MacroBuilder &Builder) const override {
737    // FIXME: _LONG_LONG should not be defined under -std=c89.
738    Builder.defineMacro("_LONG_LONG");
739    Builder.defineMacro("__370__");
740    Builder.defineMacro("__BFP__");
741    // FIXME: __BOOL__ should not be defined under -std=c89.
742    Builder.defineMacro("__BOOL__");
743    Builder.defineMacro("__COMPILER_VER__", "0x50000000");
744    Builder.defineMacro("__LONGNAME__");
745    Builder.defineMacro("__MVS__");
746    Builder.defineMacro("__THW_370__");
747    Builder.defineMacro("__THW_BIG_ENDIAN__");
748    Builder.defineMacro("__TOS_390__");
749    Builder.defineMacro("__TOS_MVS__");
750    Builder.defineMacro("__XPLINK__");
751
752    if (this->PointerWidth == 64)
753      Builder.defineMacro("__64BIT__");
754
755    if (Opts.CPlusPlus && Opts.WChar) {
756      // Macro __wchar_t is defined so that the wchar_t data
757      // type is not declared as a typedef in system headers.
758      Builder.defineMacro("__wchar_t");
759    }
760
761    this->PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
762  }
763
764public:
765  ZOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
766      : OSTargetInfo<Target>(Triple, Opts) {
767    this->WCharType = TargetInfo::UnsignedInt;
768    this->MaxAlignedAttribute = 128;
769    this->UseBitFieldTypeAlignment = false;
770    this->UseZeroLengthBitfieldAlignment = true;
771    this->UseLeadingZeroLengthBitfield = false;
772    this->ZeroLengthBitfieldBoundary = 32;
773    this->TheCXXABI.set(TargetCXXABI::XL);
774  }
775
776  bool areDefaultedSMFStillPOD(const LangOptions &) const override {
777    return false;
778  }
779};
780
781void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
782                       MacroBuilder &Builder);
783
784// Windows target
785template <typename Target>
786class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> {
787protected:
788  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
789                    MacroBuilder &Builder) const override {
790    addWindowsDefines(Triple, Opts, Builder);
791  }
792
793public:
794  WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
795      : OSTargetInfo<Target>(Triple, Opts) {
796    this->WCharType = TargetInfo::UnsignedShort;
797    this->WIntType = TargetInfo::UnsignedShort;
798  }
799};
800
801template <typename Target>
802class LLVM_LIBRARY_VISIBILITY NaClTargetInfo : public OSTargetInfo<Target> {
803protected:
804  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
805                    MacroBuilder &Builder) const override {
806    if (Opts.POSIXThreads)
807      Builder.defineMacro("_REENTRANT");
808    if (Opts.CPlusPlus)
809      Builder.defineMacro("_GNU_SOURCE");
810
811    DefineStd(Builder, "unix", Opts);
812    Builder.defineMacro("__native_client__");
813  }
814
815public:
816  NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
817      : OSTargetInfo<Target>(Triple, Opts) {
818    this->LongAlign = 32;
819    this->LongWidth = 32;
820    this->PointerAlign = 32;
821    this->PointerWidth = 32;
822    this->IntMaxType = TargetInfo::SignedLongLong;
823    this->Int64Type = TargetInfo::SignedLongLong;
824    this->DoubleAlign = 64;
825    this->LongDoubleWidth = 64;
826    this->LongDoubleAlign = 64;
827    this->LongLongWidth = 64;
828    this->LongLongAlign = 64;
829    this->SizeType = TargetInfo::UnsignedInt;
830    this->PtrDiffType = TargetInfo::SignedInt;
831    this->IntPtrType = TargetInfo::SignedInt;
832    // RegParmMax is inherited from the underlying architecture.
833    this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
834    if (Triple.getArch() == llvm::Triple::arm) {
835      // Handled in ARM's setABI().
836    } else if (Triple.getArch() == llvm::Triple::x86) {
837      this->resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
838                            "i64:64-i128:128-n8:16:32-S128");
839    } else if (Triple.getArch() == llvm::Triple::x86_64) {
840      this->resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-"
841                            "i64:64-i128:128-n8:16:32:64-S128");
842    } else if (Triple.getArch() == llvm::Triple::mipsel) {
843      // Handled on mips' setDataLayout.
844    } else {
845      assert(Triple.getArch() == llvm::Triple::le32);
846      this->resetDataLayout("e-p:32:32-i64:64");
847    }
848  }
849};
850
851// Fuchsia Target
852template <typename Target>
853class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
854protected:
855  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
856                    MacroBuilder &Builder) const override {
857    Builder.defineMacro("__Fuchsia__");
858    if (Opts.POSIXThreads)
859      Builder.defineMacro("_REENTRANT");
860    // Required by the libc++ locale support.
861    if (Opts.CPlusPlus)
862      Builder.defineMacro("_GNU_SOURCE");
863    Builder.defineMacro("__Fuchsia_API_level__", Twine(Opts.FuchsiaAPILevel));
864    this->PlatformName = "fuchsia";
865    this->PlatformMinVersion = VersionTuple(Opts.FuchsiaAPILevel);
866  }
867
868public:
869  FuchsiaTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
870      : OSTargetInfo<Target>(Triple, Opts) {
871    this->MCountName = "__mcount";
872    this->TheCXXABI.set(TargetCXXABI::Fuchsia);
873  }
874};
875
876// WebAssembly target
877template <typename Target>
878class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
879    : public OSTargetInfo<Target> {
880protected:
881  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
882                    MacroBuilder &Builder) const override {
883    // A common platform macro.
884    if (Opts.POSIXThreads)
885      Builder.defineMacro("_REENTRANT");
886    // Follow g++ convention and predefine _GNU_SOURCE for C++.
887    if (Opts.CPlusPlus)
888      Builder.defineMacro("_GNU_SOURCE");
889    // Indicate that we have __float128.
890    Builder.defineMacro("__FLOAT128__");
891  }
892
893public:
894  explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple,
895                                   const TargetOptions &Opts)
896      : OSTargetInfo<Target>(Triple, Opts) {
897    this->MCountName = "__mcount";
898    this->TheCXXABI.set(TargetCXXABI::WebAssembly);
899    this->HasFloat128 = true;
900  }
901};
902
903// WASI target
904template <typename Target>
905class LLVM_LIBRARY_VISIBILITY WASITargetInfo
906    : public WebAssemblyOSTargetInfo<Target> {
907  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
908                    MacroBuilder &Builder) const final {
909    WebAssemblyOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
910    Builder.defineMacro("__wasi__");
911  }
912
913public:
914  using WebAssemblyOSTargetInfo<Target>::WebAssemblyOSTargetInfo;
915};
916
917// Emscripten target
918template <typename Target>
919class LLVM_LIBRARY_VISIBILITY EmscriptenTargetInfo
920    : public WebAssemblyOSTargetInfo<Target> {
921  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
922                    MacroBuilder &Builder) const final {
923    WebAssemblyOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
924    DefineStd(Builder, "unix", Opts);
925    Builder.defineMacro("__EMSCRIPTEN__");
926    if (Opts.POSIXThreads)
927      Builder.defineMacro("__EMSCRIPTEN_PTHREADS__");
928  }
929
930public:
931  explicit EmscriptenTargetInfo(const llvm::Triple &Triple,
932                                const TargetOptions &Opts)
933      : WebAssemblyOSTargetInfo<Target>(Triple, Opts) {
934    // Keeping the alignment of long double to 8 bytes even though its size is
935    // 16 bytes allows emscripten to have an 8-byte-aligned max_align_t which
936    // in turn gives is a 8-byte aligned malloc.
937    // Emscripten's ABI is unstable and we may change this back to 128 to match
938    // the WebAssembly default in the future.
939    this->LongDoubleAlign = 64;
940  }
941};
942
943// OHOS target
944template <typename Target>
945class LLVM_LIBRARY_VISIBILITY OHOSTargetInfo : public OSTargetInfo<Target> {
946protected:
947  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
948                    MacroBuilder &Builder) const override {
949    // Linux defines; list based off of gcc output
950    DefineStd(Builder, "unix", Opts);
951
952    // Generic OHOS target defines
953    if (Triple.isOHOSFamily()) {
954      Builder.defineMacro("__OHOS_FAMILY__", "1");
955
956      auto Version = Triple.getEnvironmentVersion();
957      this->PlatformName = "ohos";
958      this->PlatformMinVersion = Version;
959      Builder.defineMacro("__OHOS_Major__", Twine(Version.getMajor()));
960      if (auto Minor = Version.getMinor())
961        Builder.defineMacro("__OHOS_Minor__", Twine(*Minor));
962      if (auto Subminor = Version.getSubminor())
963        Builder.defineMacro("__OHOS_Micro__", Twine(*Subminor));
964    }
965
966    if (Triple.isOpenHOS())
967      Builder.defineMacro("__OHOS__");
968
969    if (Triple.isOSLinux()) {
970      DefineStd(Builder, "linux", Opts);
971    } else if (Triple.isOSLiteOS()) {
972      Builder.defineMacro("__LITEOS__");
973    }
974
975    if (Opts.POSIXThreads)
976      Builder.defineMacro("_REENTRANT");
977    if (Opts.CPlusPlus)
978      Builder.defineMacro("_GNU_SOURCE");
979    if (this->HasFloat128)
980      Builder.defineMacro("__FLOAT128__");
981  }
982
983public:
984  OHOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
985      : OSTargetInfo<Target>(Triple, Opts) {
986    this->WIntType = TargetInfo::UnsignedInt;
987
988    switch (Triple.getArch()) {
989    default:
990      break;
991    case llvm::Triple::x86:
992    case llvm::Triple::x86_64:
993      this->HasFloat128 = true;
994      break;
995    }
996  }
997
998  const char *getStaticInitSectionSpecifier() const override {
999    return ".text.startup";
1000  }
1001};
1002
1003} // namespace targets
1004} // namespace clang
1005#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
1006