-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Forward the ABI of the non-zero sized fields of an union if they have the same ABI #55834
Conversation
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. |
r? @eddyb |
src/librustc/ty/layout.rs
Outdated
if abi == Abi::Uninhabited || size == Size::ZERO { | ||
abi = field.abi.clone(); | ||
} else if field.size != Size::ZERO && abi != field.abi { | ||
abi = Abi::Aggregate{ sized: true }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space before {
.
src/librustc/ty/layout.rs
Outdated
size = cmp::max(size, field.size); | ||
} | ||
|
||
// Use scalar_unit to reset the valid range to the maximal one | ||
// since an union might not be initialised |
There was a problem hiding this comment.
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.
src/librustc/ty/layout.rs
Outdated
@@ -697,6 +697,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { | |||
} | |||
|
|||
let mut size = Size::ZERO; | |||
let mut abi = Abi::Uninhabited; |
There was a problem hiding this comment.
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".
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
src/librustc/ty/layout.rs
Outdated
_ => field.abi.clone(), | ||
}; | ||
|
||
if abi == Abi::Uninhabited || size == Size::ZERO { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
src/librustc/ty/layout.rs
Outdated
scalar_unit(y.value), | ||
) | ||
} | ||
_ => field.abi.clone(), |
There was a problem hiding this comment.
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?
@RalfJung thanks for your review. I fixed the uninhabited case, and added some comments. |
Looks good to me now, but I also have hardly any knowledge about layout computation. |
There was a problem hiding this comment.
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.
src/test/codegen/union-abi.rs
Outdated
|
||
pub union UnionI64x4I64{ a: i64x4, b: i64 } | ||
|
||
// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}}, %UnionI64x4I64* {{.*}} %arg0) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Hang on, are we checking whether the |
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?) |
An |
@RalfJung There's a method about "are optimizations allowed" on |
I found pub fn inhibit_union_opt(&self) -> bool {
self.c()
} if we want to have all the inhibit options at the same place. Should I do that? |
@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: let mut optimize = !repr.inhibit_struct_field_reordering_opt(); Maybe the name should be |
☔ The latest upstream changes (presumably #55589) made this pull request unmergeable. Please resolve the merge conflicts. |
Should I rebase, or merge? |
Rebase.
…On Tue, Nov 13, 2018, 12:10 Olivier Goffart ***@***.*** wrote:
Please resolve the merge conflicts
Should I rebase, or merge?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#55834 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AApc0sLeeA_yV6UFE5Nxo1zbij2V34pdks5uupqYgaJpZM4YXpDz>
.
|
@bors r+ |
📌 Commit c040a48 has been approved by |
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
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
⌛ Testing commit c040a48 with merge f5a924d58abe287646f5f02ae22c5dc8153548c2... |
💔 Test failed - status-appveyor |
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
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
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)
This is supposed to fix the performence regression of using MaybeUninit in
#54668