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#ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
33#if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || \
34 (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900)
35#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1
36#else
37#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED \
38 (__has_builtin(__builtin_is_constant_evaluated))
39#endif // (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) ||
40 // (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG
41#endif // LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
42
43#ifndef LIBC_HAS_BUILTIN_BIT_CAST
44#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
45#define LIBC_HAS_BUILTIN_BIT_CAST 1
46#else
47#define LIBC_HAS_BUILTIN_BIT_CAST 0
48#endif // has_builtin(__builtin_bit_cast)
49#endif // LIBC_HAS_BUILTIN_BIT_CAST
50
51#if LIBC_HAS_BUILTIN_BIT_CAST
52#define LIBC_BIT_CAST_CONSTEXPR constexpr
53#define LIBC_BIT_CAST_CONSTEXPR_VAR constexpr
54#else
55#define LIBC_BIT_CAST_CONSTEXPR
56#define LIBC_BIT_CAST_CONSTEXPR_VAR const
57#endif // LIBC_HAS_BUILTIN_BIT_CAST
58
59#ifndef LIBC_HAS_CONSTANT_EVALUATION
60#define LIBC_HAS_CONSTANT_EVALUATION \
61 (LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST)
62#endif // LIBC_HAS_CONSTANT_EVALUATION
63
64#if LIBC_HAS_CONSTANT_EVALUATION
65#define LIBC_CONSTEXPR_DEFAULT constexpr
66#define LIBC_CONSTEXPR_VAR_DEFAULT constexpr
67#else
68#define LIBC_CONSTEXPR_DEFAULT
69#define LIBC_CONSTEXPR_VAR_DEFAULT const
70#endif // LIBC_HAS_CONSTANT_EVALUATION
71
72// TODO: Remove the macro once Clang/LLVM bump their minimum compilers' version.
73// The reason for indirection is GCC is known to fail with constexpr qualified
74// functions that doesn't produce constant expression.
75// Also, there are some circular dependency in the generic functions without
76// __builtin_func for the following functions:
77// fputil::fma
78// fputil::sqrt
79#if LIBC_ENABLE_CONSTEXPR && LIBC_HAS_CONSTANT_EVALUATION
80#define LIBC_USE_CONSTEXPR
81#define LIBC_CONSTEXPR constexpr
82#define LIBC_CONSTEXPR_VAR constexpr
83#else
84#define LIBC_CONSTEXPR
85#define LIBC_CONSTEXPR_VAR const
86#endif // LIBC_USE_CONSTEXPR
87
88#ifndef LIBC_HAS_BUILTIN_IS_ASSIGNABLE
89#if (__has_builtin(__is_assignable) || \
90 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
91#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1
92#else
93#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 0
94#endif
95#endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE
96
97#ifndef LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
98#if (__has_builtin(__is_constructible) || \
99 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
100#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
101#else
102#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
103#endif
104#endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
105
106// Uses the platform specific specialization
107#define LIBC_THREAD_MODE_PLATFORM 0
108
109// Mutex guards nothing, used in single-threaded implementations
110#define LIBC_THREAD_MODE_SINGLE 1
111
112// Vendor provides implementation
113#define LIBC_THREAD_MODE_EXTERNAL 2
114
115// libcxx doesn't define LIBC_THREAD_MODE, unless that is passed in the command
116// line in the CMake invocation. This defaults to the original implementation
117// (before changes in https://github.com/llvm/llvm-project/pull/145358)
118#ifndef LIBC_THREAD_MODE
119#define LIBC_THREAD_MODE LIBC_THREAD_MODE_PLATFORM
120#endif // LIBC_THREAD_MODE
121
122#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \
123 LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \
124 LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL
125#error LIBC_THREAD_MODE must be one of the following values: \
126LIBC_THREAD_MODE_PLATFORM, \
127LIBC_THREAD_MODE_SINGLE, \
128LIBC_THREAD_MODE_EXTERNAL.
129#endif
130
131#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE
132#define LIBC_THREAD_LOCAL
133#else
134#define LIBC_THREAD_LOCAL thread_local
135#endif
136
137#if __cplusplus >= 202002L
138#define LIBC_CONSTINIT constinit
139#elif __has_attribute(__require_constant_initialization__)
140#define LIBC_CONSTINIT __attribute__((__require_constant_initialization__))
141#else
142#define LIBC_CONSTINIT
143#endif
144
145#if defined(__clang__) && __has_attribute(preferred_type)
146#define LIBC_PREFERED_TYPE(TYPE) [[clang::preferred_type(TYPE)]]
147#else
148#define LIBC_PREFERED_TYPE(TYPE)
149#endif
150
151#if __has_attribute(ext_vector_type) && \
152 LIBC_HAS_FEATURE(ext_vector_type_boolean)
153#define LIBC_HAS_VECTOR_TYPE 1
154#else
155#define LIBC_HAS_VECTOR_TYPE 0
156#endif
157
158#if __has_attribute(no_sanitize)
159// Disable regular and hardware-supported ASan for functions that may
160// intentionally make out-of-bounds access. Disable TSan as well, as it detects
161// out-of-bounds accesses to heap memory.
162#define LIBC_NO_SANITIZE_OOB_ACCESS \
163 __attribute__((no_sanitize("address", "hwaddress", "thread")))
164#else
165#define LIBC_NO_SANITIZE_OOB_ACCESS
166#endif
167
168#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
169