Why does libcxx apply __forceinline or the GCC equivalent to its already hidden inline functions?
Asked Answered
H

1

8

I'd like to understand exactly why the libc++ visibility macro for an inline function uses __forceinline or __attribute__((__always_inline__)) as part of the attributes it associates with inline functions.

For background see:

If these inline functions are going to be marked as __visibility__("hidden") anyway, why is it necessary to additionally force the compiler to inline them?

I've thought about it a bit, and I have a few hypotheses, but none seems entirely satisfactory to me:

  • It is to ensure that the symbol does not accidentally become part of the ABI. If, while building the library, the compiler chose not to inline the function, it could potentially become an external symbol, and therefore part of the ABI. But wouldn't the hidden attribute be sufficient? Similarly, wouldn't it only be necessary to force inline the function when building the library? Consumers shouldn't care.
  • It is to ensure that the function never has a definition, to avoid ODR issues, where the compiler choses not to inline the function in the library itself, and choses not to inline in the function in the code generated by a client of the library, resulting in two different definitions. But isn't that an expected (and accepted) outcome of using visibility("hidden")?
  • It is something specific to the design of libc++ as an implementation of the standard library.

I ask this because I'm working on building a C++ library for which I hope to someday standardize an ABI, and I'm using libc++ as a guide. So far, it has worked well, but this issue has caused some head scratching.

In particular, we have had reports of users complaining that MSVC has refused to honor the __forceinline attribute, leading to warnings. Our proposed solution is to have the expansion of our analogue to INLINE_VISIBILITY only include __forceinline (or the GCC equivalent) when building the library, assuming the first explanation above.

However, since we aren't entirely confident that we understand the reasoning behind forcing inline functions to be __forceinline or __attribute__((__always_inline__)) in the first place, we are somewhat hesitant to adopt this solution.

Can anyone provide a definitive answer for why libc++ feels the need to force inline its inline functions, even though they are already decorated as having hidden visibility?

Herriott answered 2/11, 2016 at 21:19 Comment(0)
N
4

I'm probably in the best position to address this as I'm the one who did it. And you may not like the answer. :-)

When I was creating libc++ my only target was macOS (OS X). This was way before libc++ was open-sourced. And my main motivation for forcing inline was to control the ABI of the dylib that would be pushed out with OS releases. A forced inline function would never appear in a dylib, and thus I could count on it living exclusively in a header (which had a different delivery system than OS releases).

I never considered the additional attribute of "hidden" as part of this decision because it was simply an unnecessary complication for me. I wanted the function to live in a header, and never be put into a dylib and that was that. So your first bullet is I believe correct.

I am thrilled that libc++ has grown beyond its original scope and I wish you the best in continuing that effort. I'm happy to supply any additional information I might have to aid you in your goal.

Needy answered 3/11, 2016 at 0:58 Comment(1)
I like that answer fine, and thanks for taking the time to reply. It sounds like we can probably go ahead and re-evaluate whether our cargo-culting of __forceinline is unnecessary and should be removed. It sounds like it might well be. Also, if you are interested in seeing the approach we are taking or providing any feedback, the library in question is libmongocxx: github.com/mongodb/mongo-cxx-driver/tree/masterHerriott

© 2022 - 2024 — McMap. All rights reserved.