[libc++] Document our ABI guarantees and what ABI flags exist to modi… · llvm/llvm-project@f2fede6 (original) (raw)

``

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.

`