1//===-- Portable attributes -------------------------------------*- 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// This header file defines macros for declaring attributes for functions,
9// types, and variables.
10//
11// These macros are used within llvm-libc and allow the compiler to optimize,
12// where applicable, certain function calls.
13//
14// Most macros here are exposing GCC or Clang features, and are stubbed out for
15// other compilers.
16
17#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
18#define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
19
20#include "config.h"
21#include "properties/architectures.h"
22
23#ifndef __has_attribute
24#define __has_attribute(x) 0
25#endif
26
27#define LIBC_INLINE inline
28#define LIBC_INLINE_VAR inline
29#define LIBC_INLINE_ASM __asm__ __volatile__
30#define LIBC_UNUSED __attribute__((unused))
31
32#if __has_attribute(always_inline)
33#define LIBC_ALWAYS_INLINE LIBC_INLINE __attribute__((always_inline))
34#elif defined(LIBC_COMPILER_IS_MSVC) || defined(_MSC_VER)
35#define LIBC_ALWAYS_INLINE __forceinline
36#else
37#define LIBC_ALWAYS_INLINE LIBC_INLINE
38#endif // __has_attribute(always_inline)
39
40#if __has_attribute(noinline)
41#define LIBC_NOINLINE __attribute__((noinline))
42#elif defined(LIBC_COMPILER_IS_MSVC) || defined(_MSC_VER)
43#define LIBC_NOINLINE __declspec(noinline)
44#else
45#define LIBC_NOINLINE
46#endif // __has_attribute(noinline)
47
48#ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
49#if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || \
50 (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900)
51#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1
52#else
53#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED \
54 (__has_builtin(__builtin_is_constant_evaluated))
55#endif // (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) ||
56 // (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG
57#endif // LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
58
59#ifndef LIBC_HAS_BUILTIN_BIT_CAST
60#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
61#define LIBC_HAS_BUILTIN_BIT_CAST 1
62#else
63#define LIBC_HAS_BUILTIN_BIT_CAST 0
64#endif // has_builtin(__builtin_bit_cast)
65#endif // LIBC_HAS_BUILTIN_BIT_CAST
66
67#if LIBC_HAS_BUILTIN_BIT_CAST
68#define LIBC_BIT_CAST_CONSTEXPR constexpr
69#define LIBC_BIT_CAST_CONSTEXPR_VAR constexpr
70#else
71#define LIBC_BIT_CAST_CONSTEXPR
72#define LIBC_BIT_CAST_CONSTEXPR_VAR const
73#endif // LIBC_HAS_BUILTIN_BIT_CAST
74
75#ifndef LIBC_HAS_CONSTANT_EVALUATION
76#define LIBC_HAS_CONSTANT_EVALUATION \
77 (LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST)
78#endif // LIBC_HAS_CONSTANT_EVALUATION
79
80#if LIBC_HAS_CONSTANT_EVALUATION
81#define LIBC_CONSTEXPR_DEFAULT constexpr
82#define LIBC_CONSTEXPR_VAR_DEFAULT constexpr
83#else
84#define LIBC_CONSTEXPR_DEFAULT
85#define LIBC_CONSTEXPR_VAR_DEFAULT const
86#endif // LIBC_HAS_CONSTANT_EVALUATION
87
88// TODO: Remove the macro once Clang/LLVM bump their minimum compilers' version.
89// The reason for indirection is GCC is known to fail with constexpr qualified
90// functions that doesn't produce constant expression.
91// Also, there are some circular dependency in the generic functions without
92// __builtin_func for the following functions:
93// fputil::fma
94// fputil::sqrt
95#if LIBC_ENABLE_CONSTEXPR && LIBC_HAS_CONSTANT_EVALUATION
96#define LIBC_USE_CONSTEXPR
97#define LIBC_CONSTEXPR constexpr
98#define LIBC_CONSTEXPR_VAR constexpr
99#else
100#define LIBC_CONSTEXPR
101#define LIBC_CONSTEXPR_VAR const
102#endif // LIBC_USE_CONSTEXPR
103
104#ifndef LIBC_HAS_BUILTIN_IS_ASSIGNABLE
105#if (__has_builtin(__is_assignable) || \
106 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
107#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1
108#else
109#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 0
110#endif
111#endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE
112
113#ifndef LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
114#if (__has_builtin(__is_constructible) || \
115 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
116#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
117#else
118#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
119#endif
120#endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
121
122// Uses the platform specific specialization
123#define LIBC_THREAD_MODE_PLATFORM 0
124
125// Mutex guards nothing, used in single-threaded implementations
126#define LIBC_THREAD_MODE_SINGLE 1
127
128// Vendor provides implementation
129#define LIBC_THREAD_MODE_EXTERNAL 2
130
131// libcxx doesn't define LIBC_THREAD_MODE, unless that is passed in the command
132// line in the CMake invocation. This defaults to the original implementation
133// (before changes in https://github.com/llvm/llvm-project/pull/145358)
134#ifndef LIBC_THREAD_MODE
135#define LIBC_THREAD_MODE LIBC_THREAD_MODE_PLATFORM
136#endif // LIBC_THREAD_MODE
137
138#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \
139 LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \
140 LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL
141#error LIBC_THREAD_MODE must be one of the following values: \
142LIBC_THREAD_MODE_PLATFORM, \
143LIBC_THREAD_MODE_SINGLE, \
144LIBC_THREAD_MODE_EXTERNAL.
145#endif
146
147#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE
148#define LIBC_THREAD_LOCAL
149#else
150#define LIBC_THREAD_LOCAL thread_local
151#endif
152
153#if __cplusplus >= 202002L
154#define LIBC_CONSTINIT constinit
155#elif __has_attribute(__require_constant_initialization__)
156#define LIBC_CONSTINIT __attribute__((__require_constant_initialization__))
157#else
158#define LIBC_CONSTINIT
159#endif
160
161#if defined(__clang__) && __has_attribute(preferred_type)
162#define LIBC_PREFERED_TYPE(TYPE) [[clang::preferred_type(TYPE)]]
163#else
164#define LIBC_PREFERED_TYPE(TYPE)
165#endif
166
167#if __has_attribute(ext_vector_type) && \
168 LIBC_HAS_FEATURE(ext_vector_type_boolean)
169#define LIBC_HAS_VECTOR_TYPE 1
170#else
171#define LIBC_HAS_VECTOR_TYPE 0
172#endif
173
174#if __has_attribute(no_sanitize)
175// Disable regular and hardware-supported ASan for functions that may
176// intentionally make out-of-bounds access. Disable TSan as well, as it detects
177// out-of-bounds accesses to heap memory.
178#define LIBC_NO_SANITIZE_OOB_ACCESS \
179 __attribute__((no_sanitize("address", "hwaddress", "thread")))
180#else
181#define LIBC_NO_SANITIZE_OOB_ACCESS
182#endif
183
184#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
185