|
| 1 | +======================= |
| 2 | +libc++'s ABI Guarantees |
| 3 | +======================= |
| 4 | + |
| 5 | +libc++ provides multiple types ABI guarantees. These include stability of the layout of structs, the linking of TUs |
| 6 | +built against different versions and configurations of the library, and more. This document describes what guarantees |
| 7 | +libc++ provides in these different fields as well as what options exist for users and vendors to affect these |
| 8 | +guarantees. |
| 9 | + |
| 10 | +Note that all of the guarantees listed below come with an asterisk that there may be circumstances where we deem it |
| 11 | +worth it to break that guarantee. These breaks are communicated to vendors by CCing #libcxx-vendors on GitHub. If you |
| 12 | +are a vendor, please ask to be added to that group to be notified about changes that potentially affect you. |
| 13 | + |
| 14 | + |
| 15 | +Stability of the Layout of Structs |
| 16 | +================================== |
| 17 | + |
| 18 | +The layout of any struct that is observable by the user is kept stable across versions of the library and any options |
| 19 | +users are allowed to change. There are a lot of structs that have internal names, but are none the less observable by |
| 20 | +users; for example through public aliases to these types or because they affect the layout of other types. |
| 21 | + |
| 22 | +There are multiple ABI flags which affect the layout of certain structs: |
| 23 | + |
| 24 | +``_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT`` |
| 25 | +--------------------------------------- |
| 26 | +This changes the internal layout of ``basic_string`` to move the section that is used for the internal buffer to the |
| 27 | +front, making it eight byte aligned instead of being unaligned, improving the performance of some operations |
| 28 | +significantly. |
| 29 | + |
| 30 | +``_LIBCPP_ABI_NO_ITERATOR_BASES`` |
| 31 | +--------------------------------- |
| 32 | +This removes the ``std::iterator`` base class from ``back_insert_iterator``, ``front_insert_iterator``, |
| 33 | +``insert_iterator``, ``istream_iterator``, ``ostream_iterator``, ``ostreambuf_itreator``, ``reverse_iterator``, and |
| 34 | +``raw_storage_iterator``. This doesn't directly affect the layout of these types in most cases, but may result in more |
| 35 | +padding being used when they are used in combination, for example ``reverse_iterator<reverse_iterator<T>>``. |
| 36 | + |
| 37 | +- ``_LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION`` |
| 38 | +------------------------------------------------- |
| 39 | +This changes the index type used inside ``std::variant`` to the smallest required type to reduce the datasize of |
| 40 | +variants in most cases. |
| 41 | + |
| 42 | +``_LIBCPP_ABI_OPTIMIZED_FUNCTION`` |
| 43 | +---------------------------------- |
| 44 | +This significantly restructures how `std::function` is written to provide better performance, but is currently not ABI |
| 45 | +stable. |
| 46 | + |
| 47 | +``_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT`` |
| 48 | +----------------------------------------------------- |
| 49 | +This changes the layout of ``std::random_device`` to only holds state with an implementation that gets entropy from a |
| 50 | +file (see ``_LIBCPP_USING_DEV_RANDOM``). When switching from this implementation to another one on a platform that has |
| 51 | +already shipped ``std::random_device``, one needs to retain the same object layout to remain ABI compatible. This flag |
| 52 | +removes these workarounds for platforms that don't care about ABI compatibility. |
| 53 | + |
| 54 | + |
| 55 | +``_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING`` |
| 56 | +------------------------------------------ |
| 57 | +This removes artifical padding from ``_LIBCPP_COMPRESSED_PAIR`` and ``_LIBCPP_COMPRESSED_TRIPLE``. These macros are used |
| 58 | +inside the associative and unordered containers, ``deque``, ``forward_list``, ``future``, ``list``, ``basic_string``, |
| 59 | +``function``, ``shared_ptr``, ``unique_ptr``, and ``vector`` to stay ABI compatible with the legacy |
| 60 | +``__compressed_pair`` type. This has historically been used to reduce storage requirements in the case of empty types, |
| 61 | +but has been replaced by ``[[no_unique_address]]``. ``[[no_unique_address]]`` is significantly lighter in terms of |
| 62 | +compile time and debug information, and also improves the layout of structs further. However, to keep ABI stability, the |
| 63 | +additional improvements in layout had to be reverted by introducing artificial padding. |
| 64 | + |
| 65 | +``_LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE`` |
| 66 | +---------------------------------------------- |
| 67 | +``basic_ios`` uses ``WEOF`` to indicate that the fill value is uninitialized. However, on platforms where the size of |
| 68 | +``char_type`` is equal to or greater than the size of ``int_type`` and ``char_type`` is unsigned, |
| 69 | +``char_traits<char_type>::eq_int_type()`` cannot distinguish between ``WEOF`` and ``WCHAR_MAX``. This flag changes |
| 70 | +``basic_ios`` to instead track whether the fill value has been initialized using a separate boolean. |
| 71 | + |
| 72 | + |
| 73 | +Linking TUs which have been compiled against different releases of libc++ |
| 74 | +========================================================================= |
| 75 | +libc++ supports linking TUs which have beeen compiled against different releases of libc++ by marking symbols with |
| 76 | +hidden visibility and changing the mangling of header-only functions in every release. This guarantee can be disabled |
| 77 | +via ``_LIBCPP_NO_ABI_TAG``, but it is not recommended to do so. |
| 78 | + |
| 79 | + |
| 80 | +Linking TUs which have been compiled with different flags affecting code gen |
| 81 | +============================================================================ |
| 82 | +There are a lot of compiler (and library) flags which change the code generated for functions. This includes flags like |
| 83 | +``-O1``, which are guaranteed by the compiler to not change the observable behaviour of a correct program, as well as |
| 84 | +flags like ``-fexceptions``, which **do** change the observable behaviour. libc++ allows linking of TUs which have been |
| 85 | +compiled whith specific flags only and makes no guarantees for any of the flags not listed below. |
| 86 | + |
| 87 | +The flags allowed (in any combination) are: |
| 88 | +- ``-f[no-]exceptions`` |
| 89 | +- ``-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE{_FAST,_EXTENSIVE,_DEBUG,_NONE}`` |
| 90 | + |
| 91 | +Note that this does not provide any guarantees about user-defined functions, but only that the libc++ functions linked |
| 92 | +behave as the flags say. |
| 93 | + |
| 94 | + |
| 95 | +Availability of symbols in the built library (both static and shared) |
| 96 | +===================================================================== |
| 97 | +In general, libc++ does not make any guarantees about forwards-compability. That is, a TU compiled against new headers |
| 98 | +may not work with an older library. Vendors who require such support can leverage the availability markups. On the other |
| 99 | +hand, backwards compatibility is generally guaranteed. |
| 100 | + |
| 101 | +There are multiple ABI flags that change the symbols exported from the built library: |
| 102 | + |
| 103 | +``_LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON`` |
| 104 | +------------------------------------------------- |
| 105 | +This removes ``__basic_string_common<true>::__throw_length_error()`` and |
| 106 | +``__basic_string_common<true>::__throw_out_of_range()``. These symbols have been used by ``basic_string`` in the past, |
| 107 | +but are not referenced from the headers anymore. |
| 108 | + |
| 109 | +``_LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON`` |
| 110 | +------------------------------------------------ |
| 111 | +This removes ``__vector_base_common<true>::__throw_length_error()`` and |
| 112 | +``__vector_base_common<true>::__throw_out_of_range()``. These symbols have been used by ``vector`` in the past, but are |
| 113 | +not referenced from the headers anymore. |
| 114 | + |
| 115 | +``_LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10`` |
| 116 | +---------------------------------------------- |
| 117 | +This removes ``__itoa::__u32toa()`` and ``__iota::__u64toa``. These symbols have been used by ``to_chars`` in the past, |
| 118 | +but are not referenced from the headers anymore. |
| 119 | + |
| 120 | +``_LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION`` |
| 121 | +------------------------------------------------------- |
| 122 | +This replaces the symbols that are exported for ``basic_string`` to avoid exporting functions which are likely to be |
| 123 | +inlined as well as explicitly moving paths to the built library which are slow, improving fast-path inlining of multiple |
| 124 | +functions. This flag is currently unstable. |
| 125 | + |
| 126 | + |
| 127 | +Stability of the traits of a type |
| 128 | +================================= |
| 129 | +Whether a particular trait of a type is kept stable depends heavily on the type in question and the trait. The most |
| 130 | +important trait of a type to keep stable is the triviality for the purpose of calls, since that directly affects the |
| 131 | +function call ABI. Which types are considered non-trivial for the purpose of calls is defined in the |
| 132 | +`Itanium ABI <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#definitions>`_. |
| 133 | +``is_trivially_copyable`` should also be kept stable usually, since many programs depend on this trait for their own |
| 134 | +layouting. This isn't rigit as the previous requirement though. |
| 135 | + |
| 136 | +There are multiple ABI flags that change traits of a struct: |
| 137 | + |
| 138 | +``_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI`` |
| 139 | +--------------------------------------------- |
| 140 | +This flag adds ``[[clang::trivial_abi]]`` to ``unique_ptr``, which makes it trivial for the purpose of calls. |
| 141 | + |
| 142 | +``_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI`` |
| 143 | +--------------------------------------------- |
| 144 | +This flag adds ``[[clang::trivial_abi]]`` to ``shared_ptr``, which makes it trivial for the purpose of calls. |
| 145 | + |
| 146 | + |
| 147 | +Types that public aliases reference |
| 148 | +=================================== |
| 149 | +There are a lot of aliases that reference types with library internal names. For example, containers contain an |
| 150 | +``iterator`` alias to a type with a library internal name. These have to always reference the same type, since the |
| 151 | +mangling of user-defined function overloads would change otherwise. A notable exception to this are the alias templates |
| 152 | +to type traits. There doesn't seem to be anybody who relies on these names staying the same, so it is OK to change what |
| 153 | +these aliases actually reference. |
| 154 | + |
| 155 | +There are multiple ABI flags which change which type an alias references: |
| 156 | + |
| 157 | +``_LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE`` |
| 158 | +----------------------------------------- |
| 159 | +This changes ``deque::iterator`` to avoid requring complete types for ``deque``. |
| 160 | + |
| 161 | +``_LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE`` |
| 162 | +------------------------------------------------- |
| 163 | +This changes the unordered container's ``size_types`` aliases. |
| 164 | + |
| 165 | +``_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY`` and ``_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW`` |
| 166 | +----------------------------------------------------------------------------------------------- |
| 167 | +This changes the ``iterator`` and ``const_iterator`` of ``array`` and ``string_view`` respectively to reference |
| 168 | +``__wrap_iter`` instead, which makes it less likely for users to depend on non-portable implementation details. This is |
| 169 | +especially useful because enabling bounded iterators hardening requires code not to make these assumptions. |
| 170 | + |
| 171 | +``_LIBCPP_ABI_BOUNDED_ITERATORS``, ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING``, ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR``, and ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY`` |
| 172 | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 173 | +These flags change the ``iterator`` member of various classes to reference hardened iterators instead. See the |
| 174 | +:ref:`hardening documentation <_hardening>` for more details. |
| 175 | + |
| 176 | + |
| 177 | +Meaning of values |
| 178 | +================= |
| 179 | +The meaning of specific values can usually not be changed, since programs compiled against older versions of the headers |
| 180 | +may check for these values. These specific values don't have to be hard-coded, but can also depend on user input. |
| 181 | + |
| 182 | +There are multiple ABI flags that change the meaning of particular values: |
| 183 | + |
| 184 | +``_LIBCPP_ABI_REGEX_CONSTANTS_NONZERO`` |
| 185 | +--------------------------------------- |
| 186 | +This changes the value of ``regex_constants::syntax_option-type::ECMAScript`` to be standards-conforming. |
| 187 | + |
| 188 | +``_LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION`` |
| 189 | +------------------------------------------- |
| 190 | +This flag fixes the implementation of CityHash used for ``hash<fundamental-type>``. The incorrect implementation of |
| 191 | +CityHash has the roblem that it drops some bits on the floor. |
| 192 | + |
| 193 | +inline namespaces |
| 194 | +================= |
| 195 | +Inline namespaces which contain types that are ovservable by the user need to be kept the same, since they affect |
| 196 | +mangling. libc++ has almost all symbols inside an inline namespace. By default that namespace is ``__1``, but can be |
| 197 | +changed by the vendor by setting `LIBCXX_ABI_NAMESPACE` during CMake configuration. There is also |
| 198 | +``_LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE`` to remove the ``__fs``namespace from surrounding the ``filesystem`` |
| 199 | +namespace. This shortens the mangling of the filesystem symbols a bit. |
0 commit comments