Skip to content

Forward the ABI of the non-zero sized fields of an union if they have the same ABI - #55834

Merged
bors merged 2 commits into
rust-lang:masterfrom
ogoffart:union-abi
Nov 19, 2018
Merged

Forward the ABI of the non-zero sized fields of an union if they have the same ABI#55834
bors merged 2 commits into
rust-lang:masterfrom
ogoffart:union-abi

Conversation

@ogoffart

Copy link
Copy Markdown
Contributor

This is supposed to fix the performence regression of using MaybeUninit in
#54668

@rust-highfive

Copy link
Copy Markdown
Contributor

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @varkor (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 9, 2018
@varkor

Copy link
Copy Markdown
Contributor

r? @eddyb

@rust-highfiverust-highfive assigned eddyb and unassigned varkorNov 9, 2018
Comment threadsrc/librustc/ty/layout.rs Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing space before {.

Comment threadsrc/librustc/ty/layout.rs Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Need to do this before comparing field.abi above with abi, so we never compare ranges.

@eddyb

Copy link
Copy Markdown
Contributor

cc @rkruppe@nagisa@RalfJung

Comment threadsrc/librustc/ty/layout.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is the meaining of this initial value?

Notice that a union should NOT be uninhabited even if all of its fields are! That would also be a form of "propagating ranges".

@RalfJungRalfJungNov 10, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, you are using it as a sentinel value for "no non-ZST field found yet". This warrants a comment. However, we should also never use the Uninhabited layout on unions. So maybe better use an Option here, initialized to None?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think I prefer Option too.

Comment threadsrc/librustc/ty/layout.rs Outdated

@RalfJungRalfJungNov 10, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this checking for the size of the entire thing? Or whatever else size is?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, size seems to be the size of the largest field so far. That's worth a comment.
I also do not understand why we need two conditions here, shouldn't this simply be "if we have not set an abi yet"? So, shouldn't the Uninhabited test be enough?

Generally, all this new code needs a comment explaining its purpose.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The size check is for PhantomData. I think we can remove the Uninhabited test, since no fields means size is 0 anyway.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we can remove the Uninhabited test, since no fields means size is 0 anyway.

Is (u32, UninhabitedEnum) Uninhabited? What's its size?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is uninhabited at has size 4. Also see #49298.

Comment threadsrc/librustc/ty/layout.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

After this normalization, the ABI is sure to permit all bit patterns, right? There are no restrictions about what can be stored e.g. in a vector ABI type?

Comment threadsrc/librustc/ty/layout.rs Outdated
@ogoffart

Copy link
Copy Markdown
ContributorAuthor

@RalfJung thanks for your review. I fixed the uninhabited case, and added some comments.

Comment threadsrc/librustc/ty/layout.rs Outdated
Comment threadsrc/librustc/ty/layout.rs Outdated
@RalfJung

Copy link
Copy Markdown
Member

Looks good to me now, but I also have hardly any knowledge about layout computation.

@eddyb

Copy link
Copy Markdown
Contributor

LGTM but I'd like at least of @nagisa or @rkruppe to also sign off on it.

@RalfJungRalfJung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fine for me, though I think using Option would be clearer.

Comment threadsrc/test/codegen/union-abi.rs Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some of these CHECK lines seem to assume aggregates are passed as in the x86_64 SysV ABI, so if I'm not mistaken they'll fail on some other platforms. See the repr(transparent) codegen tests for what it takes to cover all/most of our targets.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ironically, the Rust default "ABI" (i.e. fn instead of extern fn) would be more consistent, in that we always pass the inner scalars for Scalar / ScalarPair.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Right, I only tested on x86_64, because that's the only arch i have. (and the test is based of the repr-transparent.rs test.) I guess this check and the next one are architecture specific. What should i do? Just remove them? Or move them somewhere else?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I used the rust ABI and removed the return value for these tests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What the repr(transparent) tests do is separate tests for each variation of how the C ABI encodes aggregates in LLVM signatures. But that's because for repr(transparent) it's important that it matches the C ABI. This PR, by contrast, is mostly about the Rust ABI and mostly about unions that shouldn't be passed as aggregates. So I don't think it needs as comprehensive coverage of extern "C" as the repr(transparent) tests, as long as we have tests somewhere that ensure that repr(C) unions are passed correctly in extern "C" calls. As long as that is true (@eddyb do you know?) I think it doesn't matter very much.

@eddyb

Copy link
Copy Markdown
Contributor

Hang on, are we checking whether the repr is C or not?
I don't think we can do this optimization for repr(C) unions.

@ogoffart

Copy link
Copy Markdown
ContributorAuthor

I just disabled the optimisation for repr(C) union. (but i don't know how i can test them: simd are not repr(c), what else would make a difference?)

@eddyb

Copy link
Copy Markdown
Contributor

An union with a large scalar (e.g. u128) should be passed as an u32 in the Rust ABI, but if you add #[repr(C)] to it, it should be passed by indirection.

@eddyb

Copy link
Copy Markdown
Contributor

@RalfJung There's a method about "are optimizations allowed" on AdtDef that we could check.

@ogoffart

Copy link
Copy Markdown
ContributorAuthor

I found ReprOptions::inhibit_enum_layout_opt and ReprOptions::inhibit_struct_field_reordering_opt . I could use inhibit_enum_layout_opt, since the second condition does not matter for unions, but that's not really a good name. Or I could add in impl ReprOptions

pubfninhibit_union_opt(&self) -> bool{self.c()}

if we want to have all the inhibit options at the same place. Should I do that?

@eddyb

Copy link
Copy Markdown
Contributor

@ogoffart I think that's good. Kind of surprised there's not a more general method in there.

All struct-related optimizations (including the newtype ABI ones!) appear to use:

letmut optimize = !repr.inhibit_struct_field_reordering_opt();

Maybe the name should be inhibit_field_abi_opt?

@bors

bors commented Nov 13, 2018

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (presumably #55589) made this pull request unmergeable. Please resolve the merge conflicts.

@ogoffart

Copy link
Copy Markdown
ContributorAuthor

Please resolve the merge conflicts

Should I rebase, or merge?

@nagisa

nagisa commented Nov 13, 2018 via email

Copy link
Copy Markdown
Member

@eddyb

Copy link
Copy Markdown
Contributor

@bors r+

@bors

bors commented Nov 15, 2018

Copy link
Copy Markdown
Collaborator

📌 Commit c040a48 has been approved by eddyb

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 15, 2018
@RalfJungRalfJung mentioned this pull request Nov 15, 2018
emilyalbini added a commit to emilyalbini/rust that referenced this pull request Nov 15, 2018
Forward the ABI of the non-zero sized fields of an union if they have the same ABI
This is supposed to fix the performence regression of using MaybeUninit in
rust-lang#54668
kennytm added a commit to kennytm/rust that referenced this pull request Nov 17, 2018
Forward the ABI of the non-zero sized fields of an union if they have the same ABI
This is supposed to fix the performence regression of using MaybeUninit in
rust-lang#54668
@kennytmkennytm mentioned this pull request Nov 17, 2018
@bors

bors commented Nov 18, 2018

Copy link
Copy Markdown
Collaborator

⌛ Testing commit c040a48 with merge f5a924d58abe287646f5f02ae22c5dc8153548c2...

@bors

bors commented Nov 18, 2018

Copy link
Copy Markdown
Collaborator

💔 Test failed - status-appveyor

@borsbors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Nov 18, 2018
@kennytm

Copy link
Copy Markdown
Member

@bors retry #56034

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 18, 2018
emilyalbini added a commit to emilyalbini/rust that referenced this pull request Nov 18, 2018
Forward the ABI of the non-zero sized fields of an union if they have the same ABI
This is supposed to fix the performence regression of using MaybeUninit in
rust-lang#54668
bors added a commit that referenced this pull request Nov 19, 2018
Rollup of 25 pull requests
Successful merges:
- #55562 (Add powerpc- and powerpc64-unknown-linux-musl targets)
- #55564 (test/linkage-visibility: Ignore on musl targets)
- #55827 (A few tweaks to iterations/collecting)
- #55834 (Forward the ABI of the non-zero sized fields of an union if they have the same ABI)
- #55857 (remove unused dependency)
- #55862 (in which the E0618 "expected function" diagnostic gets a makeover)
- #55867 (do not panic just because cargo failed)
- #55894 (miri enum discriminant handling: Fix treatment of pointers, better error when it is undef)
- #55916 (Make miri value visitor usfeful for mutation)
- #55919 (core/tests/num: Simplify `test_int_from_str_overflow()` test code)
- #55923 (reword #[test] attribute error on fn items)
- #55935 (appveyor: Use VS2017 for all our images)
- #55949 (ty: return impl Iterator from Predicate::walk_tys)
- #55952 (Update to Clang 7 on CI.)
- #55953 (#53488 Refactoring UpvarId)
- #55962 (rustdoc: properly calculate spans for intra-doc link resolution errors)
- #55963 (Stress test for MPSC)
- #55968 (Clean up some non-mod-rs stuff.)
- #55970 (Miri backtrace improvements)
- #56007 (CTFE: dynamically make sure we do not call non-const-fn)
- #56011 (Replace data.clone() by Arc::clone(&data) in mutex doc.)
- #56012 (avoid shared ref in UnsafeCell::get)
- #56016 (Add VecDeque::resize_with)
- #56027 (docs: Add missing backtick in object_safety.rs docs)
- #56043 (remove "approx env bounds" if we already know from trait)
Failed merges:
r? @ghost
bors added a commit that referenced this pull request Nov 19, 2018
Rollup of 25 pull requests
Successful merges:
- #55562 (Add powerpc- and powerpc64-unknown-linux-musl targets)
- #55564 (test/linkage-visibility: Ignore on musl targets)
- #55827 (A few tweaks to iterations/collecting)
- #55834 (Forward the ABI of the non-zero sized fields of an union if they have the same ABI)
- #55857 (remove unused dependency)
- #55862 (in which the E0618 "expected function" diagnostic gets a makeover)
- #55867 (do not panic just because cargo failed)
- #55894 (miri enum discriminant handling: Fix treatment of pointers, better error when it is undef)
- #55916 (Make miri value visitor useful for mutation)
- #55919 (core/tests/num: Simplify `test_int_from_str_overflow()` test code)
- #55923 (reword #[test] attribute error on fn items)
- #55949 (ty: return impl Iterator from Predicate::walk_tys)
- #55952 (Update to Clang 7 on CI.)
- #55953 (#53488 Refactoring UpvarId)
- #55962 (rustdoc: properly calculate spans for intra-doc link resolution errors)
- #55963 (Stress test for MPSC)
- #55968 (Clean up some non-mod-rs stuff.)
- #55970 (Miri backtrace improvements)
- #56007 (CTFE: dynamically make sure we do not call non-const-fn)
- #56011 (Replace data.clone() by Arc::clone(&data) in mutex doc.)
- #56012 (avoid shared ref in UnsafeCell::get)
- #56016 (Add VecDeque::resize_with)
- #56027 (docs: Add missing backtick in object_safety.rs docs)
- #56043 (remove "approx env bounds" if we already know from trait)
- #56059 (Increase `Duration` approximate equal threshold to 1us)
@bors
bors merged commit c040a48 into rust-lang:masterNov 19, 2018
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@ogoffart@rust-highfive@varkor@eddyb@RalfJung@bors@nagisa@kennytm@hanna-kruppe