Skip to content

Commit 47e1826

Browse files
philnik777rorth
authored andcommitted
[libc++] Document our ABI guarantees and what ABI flags exist to modify these guarantees (llvm#132615)
1 parent 1552282 commit 47e1826

File tree

5 files changed

+248
-96
lines changed

5 files changed

+248
-96
lines changed

libcxx/docs/ABIGuarantees.rst

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

libcxx/docs/UserDocumentation.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ when ``-fexperimental-library`` is passed:
8282
version has shipped. The full policy is explained :ref:`here <experimental features>`.
8383

8484

85+
.. _libcxx-configuration-macros:
86+
8587
Libc++ Configuration Macros
8688
===========================
8789

libcxx/docs/VendorDocumentation.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,8 @@ situations will give the same result:
582582
$ clang++ -stdlib=libc++ helloworld.cpp -lcxxrt
583583
584584
.. _`libcxxrt`: https://github.com/libcxxrt/libcxxrt
585+
586+
libc++'s ABI guarantees
587+
=======================
588+
589+
Libc++ provides several ABI guarantees, which are documented :ref:`here <ABIGuarantees>`.

libcxx/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Getting Started with libc++
3737
ReleaseNotes
3838
UserDocumentation
3939
VendorDocumentation
40+
ABIGuarantees
4041
Contributing
4142
CodingGuidelines
4243
TestingLibcxx

0 commit comments

Comments
 (0)