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