Skip to content

Commit 23e1ed6

Browse files
authored
[libc++] Split up ABI and platform configuration to their own headers (#90863)
This is a first step towards splitting up the <__config> header. The <__config> header is large and rather disorganized at this point, leading to confusion and subtle mistakes. For example, we never noticed that the string layout used on arm64 was only enabled for the Clang compiler, as the setting being in the compiler == clang block was probably never intentional. The danger of splitting up the <__config> header is to implicitly use undefined macros that should have been defined prior to their usage, however this can be remediated with -Wundef and we've started moving towards -Wundef enforceable macros.
1 parent d67200e commit 23e1ed6

File tree

7 files changed

+263
-191
lines changed

7 files changed

+263
-191
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,9 @@ set(files
314314
__concepts/totally_ordered.h
315315
__condition_variable/condition_variable.h
316316
__config
317+
__configuration/abi.h
318+
__configuration/compiler.h
319+
__configuration/platform.h
317320
__coroutine/coroutine_handle.h
318321
__coroutine/coroutine_traits.h
319322
__coroutine/noop_coroutine_handle.h

libcxx/include/__config

Lines changed: 3 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,16 @@
1111
#define _LIBCPP___CONFIG
1212

1313
#include <__config_site>
14+
#include <__configuration/abi.h>
15+
#include <__configuration/compiler.h>
16+
#include <__configuration/platform.h>
1417

1518
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
1619
# pragma GCC system_header
1720
#endif
1821

19-
#if defined(__apple_build_version__)
20-
// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403)
21-
# define _LIBCPP_COMPILER_CLANG_BASED
22-
# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000)
23-
#elif defined(__clang__)
24-
# define _LIBCPP_COMPILER_CLANG_BASED
25-
# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
26-
#elif defined(__GNUC__)
27-
# define _LIBCPP_COMPILER_GCC
28-
# define _LIBCPP_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
29-
#endif
30-
3122
#ifdef __cplusplus
3223

33-
// Warn if a compiler version is used that is not supported anymore
34-
// LLVM RELEASE Update the minimum compiler versions
35-
# if defined(_LIBCPP_CLANG_VER)
36-
# if _LIBCPP_CLANG_VER < 1700
37-
# warning "Libc++ only supports Clang 17 and later"
38-
# endif
39-
# elif defined(_LIBCPP_APPLE_CLANG_VER)
40-
# if _LIBCPP_APPLE_CLANG_VER < 1500
41-
# warning "Libc++ only supports AppleClang 15 and later"
42-
# endif
43-
# elif defined(_LIBCPP_GCC_VER)
44-
# if _LIBCPP_GCC_VER < 1300
45-
# warning "Libc++ only supports GCC 13 and later"
46-
# endif
47-
# endif
48-
4924
// The attributes supported by clang are documented at https://clang.llvm.org/docs/AttributeReference.html
5025

5126
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
@@ -79,135 +54,6 @@
7954
# endif // _LIBCPP_STD_VER
8055
// NOLINTEND(libcpp-cpp-version-check)
8156

82-
# if defined(__ELF__)
83-
# define _LIBCPP_OBJECT_FORMAT_ELF 1
84-
# elif defined(__MACH__)
85-
# define _LIBCPP_OBJECT_FORMAT_MACHO 1
86-
# elif defined(_WIN32)
87-
# define _LIBCPP_OBJECT_FORMAT_COFF 1
88-
# elif defined(__wasm__)
89-
# define _LIBCPP_OBJECT_FORMAT_WASM 1
90-
# elif defined(_AIX)
91-
# define _LIBCPP_OBJECT_FORMAT_XCOFF 1
92-
# else
93-
// ... add new file formats here ...
94-
# endif
95-
96-
// ABI {
97-
98-
# if _LIBCPP_ABI_VERSION >= 2
99-
// Change short string representation so that string data starts at offset 0,
100-
// improving its alignment in some cases.
101-
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
102-
// Fix deque iterator type in order to support incomplete types.
103-
# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
104-
// Fix undefined behavior in how std::list stores its linked nodes.
105-
# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
106-
// Fix undefined behavior in how __tree stores its end and parent nodes.
107-
# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
108-
// Fix undefined behavior in how __hash_table stores its pointer types.
109-
# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
110-
# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
111-
# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
112-
// Override the default return value of exception::what() for bad_function_call::what()
113-
// with a string that is specific to bad_function_call (see http://wg21.link/LWG2233).
114-
// This is an ABI break on platforms that sign and authenticate vtable function pointers
115-
// because it changes the mangling of the virtual function located in the vtable, which
116-
// changes how it gets signed.
117-
# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
118-
// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
119-
# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
120-
// Give reverse_iterator<T> one data member of type T, not two.
121-
// Also, in C++17 and later, don't derive iterator types from std::iterator.
122-
# define _LIBCPP_ABI_NO_ITERATOR_BASES
123-
// Use the smallest possible integer type to represent the index of the variant.
124-
// Previously libc++ used "unsigned int" exclusively.
125-
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
126-
// Unstable attempt to provide a more optimized std::function
127-
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
128-
// All the regex constants must be distinct and nonzero.
129-
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
130-
// Re-worked external template instantiations for std::string with a focus on
131-
// performance and fast-path inlining.
132-
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
133-
// Enable clang::trivial_abi on std::unique_ptr.
134-
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
135-
// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr
136-
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
137-
// std::random_device holds some state when it uses an implementation that gets
138-
// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this
139-
// implementation to another one on a platform that has already shipped
140-
// std::random_device, one needs to retain the same object layout to remain ABI
141-
// compatible. This switch removes these workarounds for platforms that don't care
142-
// about ABI compatibility.
143-
# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT
144-
// Don't export the legacy __basic_string_common class and its methods from the built library.
145-
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
146-
// Don't export the legacy __vector_base_common class and its methods from the built library.
147-
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
148-
// According to the Standard, `bitset::operator[] const` returns bool
149-
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
150-
// Fix the implementation of CityHash used for std::hash<fundamental-type>.
151-
// This is an ABI break because `std::hash` will return a different result,
152-
// which means that hashing the same object in translation units built against
153-
// different versions of libc++ can return inconsistent results. This is especially
154-
// tricky since std::hash is used in the implementation of unordered containers.
155-
//
156-
// The incorrect implementation of CityHash has the problem that it drops some
157-
// bits on the floor.
158-
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
159-
// Remove the base 10 implementation of std::to_chars from the dylib.
160-
// The implementation moved to the header, but we still export the symbols from
161-
// the dylib for backwards compatibility.
162-
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
163-
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
164-
// pointers, which prevents people from relying on a non-portable implementation
165-
// detail. This is especially useful because enabling bounded iterators hardening
166-
// requires code not to make these assumptions.
167-
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
168-
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
169-
# elif _LIBCPP_ABI_VERSION == 1
170-
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
171-
// Enable compiling copies of now inline methods into the dylib to support
172-
// applications compiled against older libraries. This is unnecessary with
173-
// COFF dllexport semantics, since dllexport forces a non-inline definition
174-
// of inline functions to be emitted anyway. Our own non-inline copy would
175-
// conflict with the dllexport-emitted copy, so we disable it. For XCOFF,
176-
// the linker will take issue with the symbols in the shared object if the
177-
// weak inline methods get visibility (such as from -fvisibility-inlines-hidden),
178-
// so disable it.
179-
# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
180-
# endif
181-
// Feature macros for disabling pre ABI v1 features. All of these options
182-
// are deprecated.
183-
# if defined(__FreeBSD__) && __FreeBSD__ < 14
184-
# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
185-
# endif
186-
# endif
187-
188-
// We had some bugs where we use [[no_unique_address]] together with construct_at,
189-
// which causes UB as the call on construct_at could write to overlapping subobjects
190-
//
191-
// https://github.com/llvm/llvm-project/issues/70506
192-
// https://github.com/llvm/llvm-project/issues/70494
193-
//
194-
// To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions.
195-
// The macro below is used for all classes whose ABI have changed as part of fixing these bugs.
196-
# define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua")))
197-
198-
// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's
199-
// within the bounds of the original container and asserts it on every dereference.
200-
//
201-
// ABI impact: changes the iterator type of the relevant containers.
202-
//
203-
// Supported containers:
204-
// - `span`;
205-
// - `string_view`;
206-
// - `array`.
207-
// #define _LIBCPP_ABI_BOUNDED_ITERATORS
208-
209-
// } ABI
210-
21157
// HARDENING {
21258

21359
// TODO(hardening): deprecate this in LLVM 19.
@@ -411,31 +257,10 @@ _LIBCPP_HARDENING_MODE_DEBUG
411257
# define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM
412258
# endif
413259

414-
// Need to detect which libc we're using if we're on Linux.
415-
# if defined(__linux__)
416-
# include <features.h>
417-
# if defined(__GLIBC_PREREQ)
418-
# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
419-
# else
420-
# define _LIBCPP_GLIBC_PREREQ(a, b) 0
421-
# endif // defined(__GLIBC_PREREQ)
422-
# endif // defined(__linux__)
423-
424260
# if defined(__MVS__)
425261
# include <features.h> // for __NATIVE_ASCII_F
426262
# endif
427263

428-
# ifndef __BYTE_ORDER__
429-
# error \
430-
"Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform"
431-
# endif
432-
433-
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
434-
# define _LIBCPP_LITTLE_ENDIAN
435-
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
436-
# define _LIBCPP_BIG_ENDIAN
437-
# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
438-
439264
# if defined(_WIN32)
440265
# define _LIBCPP_WIN32API
441266
# define _LIBCPP_SHORT_WCHAR 1
@@ -547,19 +372,6 @@ typedef __char32_t char32_t;
547372

548373
# if defined(_LIBCPP_COMPILER_CLANG_BASED)
549374

550-
# if defined(__APPLE__)
551-
# if defined(__i386__) || defined(__x86_64__)
552-
// use old string layout on x86_64 and i386
553-
# elif defined(__arm__)
554-
// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs
555-
# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2
556-
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
557-
# endif
558-
# else
559-
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
560-
# endif
561-
# endif
562-
563375
// Objective-C++ features (opt-in)
564376
# if __has_feature(objc_arc)
565377
# define _LIBCPP_HAS_OBJC_ARC

libcxx/include/__configuration/abi.h

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___CONFIGURATION_ABI_H
11+
#define _LIBCPP___CONFIGURATION_ABI_H
12+
13+
#include <__config_site>
14+
#include <__configuration/compiler.h>
15+
#include <__configuration/platform.h>
16+
17+
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
18+
# pragma GCC system_header
19+
#endif
20+
21+
#if _LIBCPP_ABI_VERSION >= 2
22+
// Change short string representation so that string data starts at offset 0,
23+
// improving its alignment in some cases.
24+
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
25+
// Fix deque iterator type in order to support incomplete types.
26+
# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
27+
// Fix undefined behavior in how std::list stores its linked nodes.
28+
# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
29+
// Fix undefined behavior in how __tree stores its end and parent nodes.
30+
# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
31+
// Fix undefined behavior in how __hash_table stores its pointer types.
32+
# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
33+
# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
34+
# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
35+
// Override the default return value of exception::what() for bad_function_call::what()
36+
// with a string that is specific to bad_function_call (see http://wg21.link/LWG2233).
37+
// This is an ABI break on platforms that sign and authenticate vtable function pointers
38+
// because it changes the mangling of the virtual function located in the vtable, which
39+
// changes how it gets signed.
40+
# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
41+
// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
42+
# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
43+
// Give reverse_iterator<T> one data member of type T, not two.
44+
// Also, in C++17 and later, don't derive iterator types from std::iterator.
45+
# define _LIBCPP_ABI_NO_ITERATOR_BASES
46+
// Use the smallest possible integer type to represent the index of the variant.
47+
// Previously libc++ used "unsigned int" exclusively.
48+
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
49+
// Unstable attempt to provide a more optimized std::function
50+
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
51+
// All the regex constants must be distinct and nonzero.
52+
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
53+
// Re-worked external template instantiations for std::string with a focus on
54+
// performance and fast-path inlining.
55+
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
56+
// Enable clang::trivial_abi on std::unique_ptr.
57+
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
58+
// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr
59+
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
60+
// std::random_device holds some state when it uses an implementation that gets
61+
// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this
62+
// implementation to another one on a platform that has already shipped
63+
// std::random_device, one needs to retain the same object layout to remain ABI
64+
// compatible. This switch removes these workarounds for platforms that don't care
65+
// about ABI compatibility.
66+
# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT
67+
// Don't export the legacy __basic_string_common class and its methods from the built library.
68+
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
69+
// Don't export the legacy __vector_base_common class and its methods from the built library.
70+
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
71+
// According to the Standard, `bitset::operator[] const` returns bool
72+
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
73+
// Fix the implementation of CityHash used for std::hash<fundamental-type>.
74+
// This is an ABI break because `std::hash` will return a different result,
75+
// which means that hashing the same object in translation units built against
76+
// different versions of libc++ can return inconsistent results. This is especially
77+
// tricky since std::hash is used in the implementation of unordered containers.
78+
//
79+
// The incorrect implementation of CityHash has the problem that it drops some
80+
// bits on the floor.
81+
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
82+
// Remove the base 10 implementation of std::to_chars from the dylib.
83+
// The implementation moved to the header, but we still export the symbols from
84+
// the dylib for backwards compatibility.
85+
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
86+
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
87+
// pointers, which prevents people from relying on a non-portable implementation
88+
// detail. This is especially useful because enabling bounded iterators hardening
89+
// requires code not to make these assumptions.
90+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
91+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
92+
#elif _LIBCPP_ABI_VERSION == 1
93+
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
94+
// Enable compiling copies of now inline methods into the dylib to support
95+
// applications compiled against older libraries. This is unnecessary with
96+
// COFF dllexport semantics, since dllexport forces a non-inline definition
97+
// of inline functions to be emitted anyway. Our own non-inline copy would
98+
// conflict with the dllexport-emitted copy, so we disable it. For XCOFF,
99+
// the linker will take issue with the symbols in the shared object if the
100+
// weak inline methods get visibility (such as from -fvisibility-inlines-hidden),
101+
// so disable it.
102+
# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
103+
# endif
104+
// Feature macros for disabling pre ABI v1 features. All of these options
105+
// are deprecated.
106+
# if defined(__FreeBSD__) && __FreeBSD__ < 14
107+
# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
108+
# endif
109+
#endif
110+
111+
// We had some bugs where we use [[no_unique_address]] together with construct_at,
112+
// which causes UB as the call on construct_at could write to overlapping subobjects
113+
//
114+
// https://github.com/llvm/llvm-project/issues/70506
115+
// https://github.com/llvm/llvm-project/issues/70494
116+
//
117+
// To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions.
118+
// The macro below is used for all classes whose ABI have changed as part of fixing these bugs.
119+
#define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua")))
120+
121+
// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's
122+
// within the bounds of the original container and asserts it on every dereference.
123+
//
124+
// ABI impact: changes the iterator type of the relevant containers.
125+
//
126+
// Supported containers:
127+
// - `span`;
128+
// - `string_view`;
129+
// - `array`.
130+
// #define _LIBCPP_ABI_BOUNDED_ITERATORS
131+
132+
#if defined(_LIBCPP_COMPILER_CLANG_BASED)
133+
# if defined(__APPLE__)
134+
# if defined(__i386__) || defined(__x86_64__)
135+
// use old string layout on x86_64 and i386
136+
# elif defined(__arm__)
137+
// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs
138+
# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2
139+
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
140+
# endif
141+
# else
142+
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
143+
# endif
144+
# endif
145+
#endif
146+
147+
#endif // _LIBCPP___CONFIGURATION_ABI_H

0 commit comments

Comments
 (0)