Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use weak_odr linkage when reusing definitions across codegen units #32557

Merged
merged 1 commit into from
Mar 29, 2016

Conversation

dotdash
Copy link
Contributor

@dotdash dotdash commented Mar 28, 2016

When reuing a definition across codegen units, we obviously cannot use
internal linkage, but using external linkage means that we can end up
with multiple conflicting definitions of a single symbol across
multiple crates. Since the definitions should all be equal
semantically, we can use weak_odr linkage to resolve the situation.

Fixes #32518

r? @nikomatsakis

@@ -139,6 +139,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

if trans_everywhere || is_first {
trans_fn(ccx, decl, body, lldecl, psubsts, fn_node_id);
} else {
llvm::SetLinkage(lldecl, llvm::ExternalLinkage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as we said on IRC, this is subtle -- comment would be good

@nikomatsakis
Copy link
Contributor

r=me w/ comment

@dotdash
Copy link
Contributor Author

dotdash commented Mar 28, 2016

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 28, 2016

📌 Commit fdaea82 has been approved by nikomatsakis

@nikomatsakis
Copy link
Contributor

can't really see what travis is complaining about; looks spurious

@michaelwoerister
Copy link
Member

The LLVM document says

Unreferenced linkonce globals are allowed to be discarded.

Could that be the problem for these undefined reference errors?

@michaelwoerister
Copy link
Member

weak_odr linkage might be a better fit then...

@dotdash
Copy link
Contributor Author

dotdash commented Mar 28, 2016

No, it's probably just that linkonce_odr must only be used for things that are actually translated in every crate, not everything. IOW update_linkage was the wrong place to do this.

@michaelwoerister
Copy link
Member

base::internalize_symbols might also be something to look at.

@dotdash
Copy link
Contributor Author

dotdash commented Mar 28, 2016

Actually, you're right about using weak_odr. The whole point is that with codegen units, we're not even translating generics in every unit. D'oh!

And I should adjust base::internalize_symbols as well. I already had that and thought I had undone it for a reason, but I can't think of anything, so probably an accident.

@dotdash dotdash force-pushed the issue-32518 branch 2 times, most recently from 023a1b3 to 88cef8f Compare March 28, 2016 21:13
@nikomatsakis
Copy link
Contributor

@bors r+ p=1

@bors
Copy link
Contributor

bors commented Mar 28, 2016

📌 Commit 88cef8f has been approved by nikomatsakis

@dotdash dotdash changed the title Use linkonce_odr linkage when reusing definitions across codegen units Use weak_odr linkage when reusing definitions across codegen units Mar 28, 2016
@nikomatsakis
Copy link
Contributor

@bors r-

per conversation on IRC, this should have some sort of comment, since the boolean logic is pretty subtle, and the meaning of these flags not 100% obvious

@dotdash dotdash force-pushed the issue-32518 branch 3 times, most recently from 673b1d4 to 5fa4b63 Compare March 28, 2016 23:05
@nikomatsakis
Copy link
Contributor

much better :)

@nikomatsakis
Copy link
Contributor

@bors r+ p=1

@bors
Copy link
Contributor

bors commented Mar 28, 2016

📌 Commit 5fa4b63 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 29, 2016

⌛ Testing commit 5fa4b63 with merge 2aef71e...

@bors
Copy link
Contributor

bors commented Mar 29, 2016

💔 Test failed - auto-win-gnu-64-nopt-t

@alexcrichton
Copy link
Member

Hm I wonder if the weak odr linkage isn't supported on all platforms? It sounds like something that'd be Linux only unfortunately :(

@dotdash
Copy link
Contributor Author

dotdash commented Mar 29, 2016

Turns out that you need to use comdat sections to make this work.

http://www.airs.com/blog/archives/52 has some details.

@michaelwoerister
Copy link
Member

From the LLVM documentation on comdat sections:

Note that the Mach-O platform doesn’t support COMDATs

Do you know how this affects us? How do they do C++ templates there?

@dotdash
Copy link
Contributor Author

dotdash commented Mar 29, 2016

@michaelwoerister The check in the LLVMRustSetComdat function takes care not to set comdat for Mach-O. Weak/Linkonce_ODR + Comdat is what Clang does. I suppose that weak_odr already does the trick for Mach-O as it does for ELF.

@@ -2149,6 +2151,12 @@ pub fn SetLinkage(global: ValueRef, link: Linkage) {
}
}

pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
unsafe {
LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function needs a comment; at minimum, it should link to that blog post, but also: why does it make sense to use LLVMGetValueName here?

I would expect the string to be the symbol name or something similar -- does that happen to be what LLVMGetValueName is returning here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the returned string is the name of the function.

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Mar 29, 2016

📌 Commit 0192e54 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 29, 2016

⌛ Testing commit 0192e54 with merge 5c50dff...

@michaelwoerister
Copy link
Member

@dotdash OK, sounds good then!

@dotdash
Copy link
Contributor Author

dotdash commented Mar 29, 2016

@bors r- Forgot to unset comdat in internalize_symbols

When reuing a definition across codegen units, we obviously cannot use
internal linkage, but using external linkage means that we can end up
with multiple conflicting definitions of a single symbol across
multiple crates. Since the definitions should all be equal
semantically, we can use weak_odr linkage to resolve the situation.

Fixes rust-lang#32518
@dotdash
Copy link
Contributor Author

dotdash commented Mar 29, 2016

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 29, 2016

📌 Commit 22f4587 has been approved by nikomatsakis

@alexcrichton
Copy link
Member

Nice find! I've always wondered what comdats are...

@bors
Copy link
Contributor

bors commented Mar 29, 2016

⌛ Testing commit 22f4587 with merge b3d940a...

@bors
Copy link
Contributor

bors commented Mar 29, 2016

💔 Test failed - auto-mac-ios-opt

@alexcrichton
Copy link
Member

@bors: retry

On Tue, Mar 29, 2016 at 8:04 AM, bors notifications@github.com wrote:

[image: 💔] Test failed - auto-mac-ios-opt
http://buildbot.rust-lang.org/builders/auto-mac-ios-opt/builds/708


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#32557 (comment)

@bors
Copy link
Contributor

bors commented Mar 29, 2016

⌛ Testing commit 22f4587 with merge 8f5c3f1...

bors added a commit that referenced this pull request Mar 29, 2016
Use weak_odr linkage when reusing definitions across codegen units

When reuing a definition across codegen units, we obviously cannot use
internal linkage, but using external linkage means that we can end up
with multiple conflicting definitions of a single symbol across
multiple crates. Since the definitions should all be equal
semantically, we can use weak_odr linkage to resolve the situation.

Fixes #32518

r? @nikomatsakis
@bors bors merged commit 22f4587 into rust-lang:master Mar 29, 2016
@michaelwoerister
Copy link
Member

💖

@nikomatsakis
Copy link
Contributor

@dotdash you suggested on IRC that there may still be further problems in this area -- any update on that?

@dotdash
Copy link
Contributor Author

dotdash commented Mar 29, 2016

I think that was just about not unsetting the comdat section when
internalizing after trans has finished.

I didn't notify about the fix for that on IRC, but it's on the merged
commit.
Am 30.03.2016 00:40 schrieb "Niko Matsakis" notifications@github.com:

@dotdash https://github.com/dotdash you suggested on IRC that there may
still be further problems in this area -- any update on that?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#32557 (comment)

@brson
Copy link
Contributor

brson commented Apr 11, 2016

In my previous experiments weak_odr functions didn't optimize as well as internal functions so this may be a perf regression.

Edit: oh this is changing from external to weak_odr, not internal to weak_odr.

@dotdash dotdash deleted the issue-32518 branch May 17, 2016 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

multiple definition link error when using multiple codegen units
6 participants