This is an archive of the discontinued LLVM Phabricator instance.

[ItaniumCXXABI] Make tls wrappers properly comdat
ClosedPublic

Authored by mstorsjo on Dec 16 2019, 2:24 PM.

Details

Summary

Just marking a symbol as weak_odr/linkonce_odr isn't enough for actually tolerating multiple copies of it at linking on windows, it has to be made a proper comdat.

This should hopefully fix https://bugzilla.mozilla.org/show_bug.cgi?id=1566288.

Diff Detail

Event Timeline

mstorsjo created this revision.Dec 16 2019, 2:24 PM
Herald added a project: Restricted Project. · View Herald TranscriptDec 16 2019, 2:24 PM
rnk added inline comments.Dec 16 2019, 2:29 PM
clang/lib/CodeGen/ItaniumCXXABI.cpp
2519–2520

I would say that this is inaccurate. It greatly affects what the optimizer is allowed to do.

It looks like we forgot to put a comdat on these things, is that not the correct fix?

Actually, this doesn't seem to be enough for the case at hand (used with -ffunction-sections -fdata-sections), I'll have to continue looking into it tomorrow.

mstorsjo marked an inline comment as done.Dec 16 2019, 2:31 PM
mstorsjo added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2519–2520

Oh, ok.

The full case I was trying to fix (but forgot to recheck after changing this bit) is that when used with -ffunction-sections, the tls wrapper function ends up as comdat one_only, which then gives multiple definition errors. So perhaps the issue is in the handling of -ffunction-sections wrt weak_odr?

rnk added inline comments.Dec 16 2019, 2:58 PM
clang/lib/CodeGen/ItaniumCXXABI.cpp
2519–2520

Ah, that is an interesting wrinkle. I'm surprised that things worked without -ffunction-sections, though. I would've expected the two plain external definitions to produce multiple definition errors.

rsmith added a subscriber: rsmith.Dec 16 2019, 6:51 PM
rsmith added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2522

I think the thread wrapper should probably be linkonce_odr across all platforms, at least in all TUs that don't contain a definition of the variable. Every such TU is supposed to provide its own copy regardless, so making it non-discardable seems to serve no purpose.

That said, I suspect this is only hiding the real problem (by discarding the symbol before it creates a link error), and you'd still get link errors if you have two TUs that both use the same thread-local variable and happen to not inline / discard their thread wrappers.

mstorsjo marked 2 inline comments as done.Dec 17 2019, 12:43 AM
mstorsjo added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2519–2520

Without -ffunction-sections, there's no separate thread wrapper produced at all, so everything else is generated with working linkage. I just haven't happened to build code that forces generation of a tls wrapper without -ffunction-sections yet.

2522

There's actually a case already where these are made linkonce for other TUs at https://github.com/llvm/llvm-project/blob/master/clang/lib/CodeGen/ItaniumCXXABI.cpp#L2639-L2642:

// If this isn't a TU in which this variable is defined, the thread
// wrapper is discardable.
if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
  Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);

In what cases would two TUs create two non-inline/discardable wrappers - and wouldn't that cause similar linking errors on other platforms as well?

mstorsjo marked an inline comment as done.Dec 17 2019, 4:14 AM
mstorsjo added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2519–2520

Actually, sorry, I misremembered. Yes, I think the same issue would be present even without -ffunction-sections.

mstorsjo updated this revision to Diff 234269.Dec 17 2019, 4:17 AM
mstorsjo retitled this revision from [ItaniumCXXABI] Use linkonce_odr instead of weak_odr for tls wrappers on Windows to [ItaniumCXXABI] Make tls wrappers comdat on Windows.
mstorsjo edited the summary of this revision. (Show Details)
mstorsjo added a reviewer: rsmith.

Changed to make it a comdat; unless I'm mistaken, neither linkonce_odr nor weak_odr actually make it possible to link multiple copies of the symbol on windows, unless it's made a comdat. With that in place, the previous change (weak_odr to linkonce_odr) actually isn't needed.

rnk added inline comments.Dec 17 2019, 2:05 PM
clang/lib/CodeGen/ItaniumCXXABI.cpp
2551

IMO we should be doing the same thing on ELF, you can see the code pattern used elsewhere:
http://llvm-cs.pcc.me.uk/?q=setComdat

Before comdats were made explicit in the IR and we stopped implicitly making comdat groups for odr things on ELF, these wrappers would've been in a comdat group.

mstorsjo marked an inline comment as done.Dec 17 2019, 2:24 PM
mstorsjo added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2551

Ok, so remove the isOSWindows() and maybe remove the comment altogether as it isn't windows specific any longer?

mstorsjo marked an inline comment as done.Dec 17 2019, 2:32 PM
mstorsjo added inline comments.
clang/lib/CodeGen/ItaniumCXXABI.cpp
2551

In the current tests, for linux there's explicit checks that these aren't marked as comdat, see e.g. https://github.com/llvm/llvm-project/blob/master/clang/test/CodeGenCXX/cxx11-thread-local.cpp#L208. Is there a specific reason for that, or should it be changed?

rnk added a comment.Dec 17 2019, 3:32 PM

Looks like @rsmith did this here:
https://github.com/llvm/llvm-project/commit/fbe2369f1a514423e4c25417ab3532502fde6f2a

I see that it was replacing a CHECK for a specific comdat group with no comdat at all. I *think* that's not correct, we should be checking for the trivial comdat group, the one for the wrapper function, not the comdat group of the TLS variable. Let's get input from Richard, though.

In D71572#1788786, @rnk wrote:

Looks like @rsmith did this here:
https://github.com/llvm/llvm-project/commit/fbe2369f1a514423e4c25417ab3532502fde6f2a

I see that it was replacing a CHECK for a specific comdat group with no comdat at all. I *think* that's not correct, we should be checking for the trivial comdat group, the one for the wrapper function, not the comdat group of the TLS variable. Let's get input from Richard, though.

@rsmith?

rsmith added inline comments.Jan 7 2020, 10:50 AM
clang/lib/CodeGen/ItaniumCXXABI.cpp
2551

The test is intending to check that the wrapper is not in a comdat keyed off the variable. Putting it in a trivial comdat is fine and correct; please update the tests to check that it's in the right comdat, not just that it's in some comdat. (I seem to regularly forget that weak / linkonce / weak_odr / linkonce_odr don't actually work as documented any more...)

mstorsjo updated this revision to Diff 236664.Jan 7 2020, 12:13 PM
mstorsjo retitled this revision from [ItaniumCXXABI] Make tls wrappers comdat on Windows to [ItaniumCXXABI] Make tls wrappers properly comdat.
mstorsjo edited the summary of this revision. (Show Details)

Making the tls wrappers comdat on any platform that supports comdat; updated tests accordingly.

@rsmith - does this look right to you?

@rnk and/or @rsmith - can either of you have a look at the new version of this?

rnk accepted this revision.Jan 13 2020, 1:08 PM

lgtm

This will be a small change in behavior, but nobody on ELF should notice because things with vague linkage there are both ELF-weak and comdat.

clang/lib/CodeGen/ItaniumCXXABI.cpp
2551

I think this is the confirmation you need, the new tests look correct to me.

This revision is now accepted and ready to land.Jan 13 2020, 1:08 PM
This revision was automatically updated to reflect the committed changes.