When I recently looked at the v0 name mangling scheme, I was confused why generics had a suffix that is not based on the crate that defined the generic, but the one that instantiated it, because that makes using ODR linkage to avoid duplicate function definitions in the final binary impossible due to different symbol names. I then looked through the code and noticed that ODR linkage is gone. We used to use ODR linkage for generics when codegen units were introduced, but it seems to have been removed when incremental compilation has been introduced. Is that because there were problems that completely prohibit ODR linkage in the context of incremental compilation, or was it just the easier approach at the time? After all, the old name mangling scheme made ODR across crates impossible as well, but I had hoped that the new one would allow for it.
cc @mw ^
I don't think there are conceptual reasons for not using ODR linkage. If I remember correctly the reasons we removed it were:
However, that was a long time ago (2016?) and those reasons might not be valid anymore. In fact, I hoped that I or someone else would look into reenabling ODR linkage in the first half of this year. It would make some things easier to implement and it might reduce code size (maybe even compile times?)
Questions that would need clarification:
The new mangling scheme supports those "instantiating crate" suffixes because the compiler currently needs them. But the suffixes could just be omitted.
Looking back at some old issues, the MingW issue seems to be related specifically to the use of weak symbols. I'm wondering why weak_odr rather than linkonce_odr was used at the time.
- Does ODR linkage adversely affect runtime performance?
All of {LinkOnce,Weak}{Any,ODR} block some interprocedural analyses and optimizations for reasons described here https://www.playingwithpointers.com/blog/ipo-and-derefinement.html
If you want to know what it affects exactly in LLVM, GlobalValue
has helper methods hasExactDefinition
/ isDefinitionExact
which return false for those cases and ought to be used whenever this is relevant.
Thanks for the reference, that's pretty unfortunate.
Binutils (AS and LD BFD) are very buggy when it comes to weak symbols on MinGW. Clang doesn't yet allow weak symbols for MinGW (turns them into global symbols) but if you force it things seem to work just fine when using LLD.
Even more, LLD can propely link objects with weak symbols created by GCC + Binutils AS.
Over 11 years old open issue: https://sourceware.org/bugzilla/show_bug.cgi?id=9687
Weak symbols really only work on ELF.
weak_odr was used because back then (not sure if that would still be the case), the symbol might otherwise be optimized away, while other compilation units still depend on it, because the optimizer doesn't know about the other compilation units