-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Support s390x z13 vector ABI #131586
Support s390x z13 vector ABI #131586
Conversation
This comment has been minimized.
This comment has been minimized.
r? compiler |
7656805
to
07ca922
Compare
This comment has been minimized.
This comment has been minimized.
c14d9b2
to
d39e822
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
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.
In addition to the problem mentioned inline, we should also verify that building with soft-float works as expected. This option implicitly disables any use of floating-point or vector registers, and therefore also disables use of the vector facility. I believe the LLVM back-end should handle that logic correctly, but it would be good to have the test check.
0a6b7ad
to
c1835bd
Compare
This comment has been minimized.
This comment has been minimized.
c1835bd
to
f4f0361
Compare
This comment has been minimized.
This comment has been minimized.
f4f0361
to
e18682e
Compare
This comment has been minimized.
This comment has been minimized.
5fc1014
to
6718371
Compare
This comment has been minimized.
This comment has been minimized.
6718371
to
730ecfe
Compare
tests/assembly/s390x-vector-abi.rs
Outdated
// CHECK-LABEL: vector_wrapper_with_zst_arg_small: | ||
// CHECK: vlgvg %r2, %v24, 0 | ||
// CHECK-NEXT: br %r14 | ||
#[cfg_attr(no_vector, target_feature(enable = "vector"))] | ||
#[no_mangle] | ||
unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst<i8x8>) -> i64 { |
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 current implementation of this PR ignores ZST (zero sized type) in a structure, is this incorrect? Or is the current implementation where ZST is specifically ignored correct?
From the ABI doc mentioned in PR description:
‹vector_arg›: A vector_arg has one of the following types:
- Any vector type whose size is 16 bytes or less.
- A structure equivalent to such a vector type, where “equivalent” has the same meaning as for double_or_float.
And double_or_float is:
‹double_or_float›: A double_or_float is one of the following:
- A float or _Decimal32.
- A double or _Decimal64.
- A structure equivalent to one of the above. A structure is equivalent to a type 𝑇 if and only if it has exactly one member, which is either of type 𝑇 itself or a structure equivalent to type 𝑇.
Looking at the existing code, is the handling of ZST platform dependent? (#125854)
rust/compiler/rustc_target/src/callconv/s390x.rs
Lines 45 to 54 in 730ecfe
if arg.is_ignore() { | |
// s390x-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. | |
if cx.target_spec().os == "linux" | |
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") | |
&& arg.layout.is_zst() | |
{ | |
arg.make_indirect_from_ignore(); | |
} | |
return; | |
} |
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.
This is unfortunately a bit more complicated due to historical reasons. For the purposes of deciding whether an aggregate is a "structure equivalent to a float or vector", zero-sized members in C are not ignored. The presence of a zero-sized bitfield, nested struct, or nested array member does make the aggregate not equivalent, i.e. it will be passed in GPRs and not in FPRs/VRs.
However, for C++ types, there are some zero-sized members that are ignored; this applies in particular to zero-sized base classes as well as C++20 empty data members (marked with [[no_unique_address]]
). This is not currently documented in the ABI (but then again, the ABI doesn't document anything about C++ ...).
The question is, what does this now mean for Rust? My understanding is that Rust here attempts to be ABI-compatible with C only (not C++), and therefore I think it makes sense that Rust should be treated like C, i.e. zero-sized members are not ignored. Current Rust code seems to correctly implement this for FP types via is_single_fp_element
, so I think this PR should do the same for vector types.
As to the second question, what if the whole argument is zero-sized? Both the strict reading of the ABI document and the actual GCC/clang implementation agree that this is passed via implicit pointer (which arguably doesn't make much sense, but we cannot change this anymore). So the current Rust code looks correct to me.
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.
Thanks. I fixed this PR's implementation by adding&using is_single_vector_element based on is_single_fp_element.
rust/tests/assembly/s390x-vector-abi.rs
Lines 251 to 265 in 55d960e
// CHECK-LABEL: vector_wrapper_with_zst_arg_small: | |
// CHECK: .cfi_startproc | |
// CHECK-NOT: vlgvg | |
// CHECK-NEXT: br %r14 | |
#[cfg_attr(no_vector, target_feature(enable = "vector"))] | |
#[no_mangle] | |
unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst<i8x8>) -> i64 { | |
unsafe { *(&x as *const WrapperWithZst<i8x8> as *const i64) } | |
} | |
// CHECK-LABEL: vector_wrapper_with_zst_arg: | |
// CHECK: lg %r2, 0(%r2) | |
// CHECK-NEXT: br %r14 | |
#[cfg_attr(no_vector, target_feature(enable = "vector"))] | |
#[no_mangle] | |
unsafe extern "C" fn vector_wrapper_with_zst_arg(x: WrapperWithZst<i8x16>) -> i64 { |
f5a7735
to
55d960e
Compare
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { | ||
|
||
let size = arg.layout.size; | ||
if size.bits() <= 128 && arg.layout.is_single_vector_element(cx) { |
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.
There's one more quirk I think we need to handle here: for single-element vector aggregates, the aggregate must have no padding, i.e. the aggregate size must match the vector size. (This is different for FP aggregates, where e.g. an 8-byte aligned struct with a single float element is passed like a double.)
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, good catch. Older versions of this PR had a check for that, but I accidentally removed it when I rewrote it based on is_single_fp_element.
Re-added size check and added a test for this case:
rust/tests/assembly/s390x-vector-abi.rs
Lines 265 to 271 in 1bd1416
// https://github.com/rust-lang/rust/pull/131586#discussion_r1837071121 | |
// CHECK-LABEL: vector_wrapper_padding_arg: | |
// CHECK: lg %r2, 0(%r2) | |
// CHECK-NEXT: br %r14 | |
#[cfg_attr(no_vector, target_feature(enable = "vector"))] | |
#[no_mangle] | |
unsafe extern "C" fn vector_wrapper_padding_arg(x: WrapperAlign16<i8x8>) -> i64 { |
55d960e
to
1bd1416
Compare
This comment has been minimized.
This comment has been minimized.
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.
Thanks! This now looks fully correct from an s390x ABI perspective.
1bd1416
to
d324817
Compare
☔ The latest upstream changes (presumably #133006) made this pull request unmergeable. Please resolve the merge conflicts. |
d324817
to
9507b11
Compare
This comment has been minimized.
This comment has been minimized.
9507b11
to
7652e34
Compare
@bors r=compiler-errors,uweigand |
…iaskrgr Rollup of 6 pull requests Successful merges: - rust-lang#130236 (unstable feature usage metrics) - rust-lang#131544 (Make asm label blocks safe context) - rust-lang#131586 (Support s390x z13 vector ABI) - rust-lang#132489 (Fix closure arg extraction in `extract_callable_info`, generalize it to async closures) - rust-lang#133078 (tests: ui/inline-consts: add issue number to a test, rename other tests) - rust-lang#133283 (Don't exclude relnotes from `needs-triage` label) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#131586 - taiki-e:s390x-vector-abi, r=compiler-errors,uweigand Support s390x z13 vector ABI cc rust-lang#130869 This resolves the following fixmes: - https://github.com/rust-lang/rust/blob/58420a065b68ecb3eec03b942740c761cdadd5c4/compiler/rustc_target/src/abi/call/s390x.rs#L1-L2 - https://github.com/rust-lang/rust/blob/58420a065b68ecb3eec03b942740c761cdadd5c4/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs#L9-L11 Refs: Section 1.2.3 "Parameter Passing" and section 1.2.5 "Return Values" in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1) This PR extends ~~rust-lang#127731 rust-lang#132173 (merged) 's ABI check to handle cases where `vector` target feature is disabled. If we do not do ABI check, we run into the ABI problems as described in rust-lang#116558 and rust-lang#130869 (comment), and the problem of the compiler generating strange code (rust-lang#131586 (comment)). cc `@uweigand` `@rustbot` label +O-SystemZ +A-ABI
cc #130869
This resolves the following fixmes:
rust/compiler/rustc_target/src/abi/call/s390x.rs
Lines 1 to 2 in 58420a0
rust/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
Lines 9 to 11 in 58420a0
Refs: Section 1.2.3 "Parameter Passing" and section 1.2.5 "Return Values" in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
This PR extends
#127731#132173 (merged) 's ABI check to handle cases wherevector
target feature is disabled.If we do not do ABI check, we run into the ABI problems as described in #116558 and #130869 (comment), and the problem of the compiler generating strange code (#131586 (comment)).
cc @uweigand
@rustbot label +O-SystemZ +A-ABI