Index: docs/DesignDocs/ABIVersioning.rst =================================================================== --- docs/DesignDocs/ABIVersioning.rst +++ docs/DesignDocs/ABIVersioning.rst @@ -15,3 +15,40 @@ Any ABI-changing feature is placed under it's own macro, _LIBCPP_ABI_XXX, which is enabled based on the value of _LIBCPP_ABI_VERSION. _LIBCPP_ABI_UNSTABLE, if set, enables all features at once. + +======================== +Always_inline attributes +======================== + +To ensure ABI stability, libc++ attempts to tightly control the set of +symbols exported from libc++.so. This is achieved with a "trick" of +marking all functions and class methods defined in the library headers +on Linux/MacOSX with:: + + __attribute__((always_inline, visibility("hidden"))) + +All direct calls to functions marked with the always_inline attribute +are inlined and are never emitted as an external symbol +reference. Hidden visibility removes the symbol from the shared +library exports list. + +This approach has a number of drawbacks. + +* always_inline functions are not always inlined. Inlining is an + optimization, and there are multiple cases when a compiler can + decide against it. + + * As of version 3.7, Clang can sometimes emit an **unreachable** + call to an always_inline function as an external symbol reference. + * Inlining may be impossible between functions with incompatible + attributes. For example, ``__attribute__((no_sanitize_address))``, + which suppresses AddressSanitizer instrumentation in a function, + prevents inlining of functions that do not have the same + attribute. + +* At -O0 optimization level indiscriminate inlining results in very + large stack frames. As a consequence, removing these attributes + speeds up libc++ test suite by 10%. + +These attributes are removed when building with +LIBCXX_ABI_UNSTABLE=ON. Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -31,6 +31,13 @@ #define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT #endif +#if defined(_LIBCPP_ABI_UNSTABLE) +// The only purpose of the always_inline thing is ABI stability. +// Disable it when building for unstable ABI. +#define _LIBCPP_INLINE_VISIBILITY +#define _LIBCPP_ALWAYS_INLINE +#endif + #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y #define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)