-
Notifications
You must be signed in to change notification settings - Fork 14k
Rework c_variadic
#141980
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
base: master
Are you sure you want to change the base?
Rework c_variadic
#141980
Conversation
|
This PR modifies cc @jieyouxu Some changes occurred in compiler/rustc_codegen_ssa |
cb90479 to
23a983d
Compare
This comment was marked as outdated.
This comment was marked as outdated.
I've just ran
I ran the assembly test you supplied locally and got this assembly: Test assembly .file "temp.9a048525d681a25f-cgu.0"
.section .text.by_reference,"ax",@progbits
.globl by_reference
.p2align 4
.type by_reference,@function
by_reference:
.cfi_startproc
movl (%rdi), %ecx
cmpq $40, %rcx
ja .LBB0_2
movq %rcx, %rax
addq 16(%rdi), %rax
addl $8, %ecx
movl %ecx, (%rdi)
movl (%rax), %eax
retq
.LBB0_2:
movq 8(%rdi), %rax
leaq 8(%rax), %rcx
movq %rcx, 8(%rdi)
movl (%rax), %eax
retq
.Lfunc_end0:
.size by_reference, .Lfunc_end0-by_reference
.cfi_endproc
.section .text.dummy,"ax",@progbits
.globl dummy
.p2align 4
.type dummy,@function
dummy:
.cfi_startproc
retq
.Lfunc_end1:
.size dummy, .Lfunc_end1-dummy
.cfi_endproc
.globl by_value
.type by_value,@function
.set by_value, by_reference
.ident "rustc version 1.89.0-dev"
.section ".note.GNU-stack","",@progbitsLLVM appears to have merged the functions as they had identical assembly.
|
I am somewhat uncomfortable relying on that, and would personally prefer a slightly less slick API that requires fewer hacks. This feature is too niche to justify so much hackery, IMO. But maybe I am overly paranoid. If we do end up going for it, please add walls of comments everywhere that explain this, or else we can be sure some poor compiler contributor will spend hours digging through this in a few years... |
|
@beetrees hmm, I did rebase, maybe that messed something up? Can you rebase this branch to something more recent? |
23a983d to
57bc996
Compare
|
I've rebased, and the two tests still pass locally. |
|
For me too, I must have messed something up earlier. Thanks for checking! |
57bc996 to
6347a21
Compare
6347a21 to
6e1e74f
Compare
|
I've reworked this to use a |
This comment has been minimized.
This comment has been minimized.
6e1e74f to
26f7025
Compare
26f7025 to
79a6396
Compare
|
|
This comment has been minimized.
This comment has been minimized.
3d5e0ce to
ca9c162
Compare
|
☔ The latest upstream changes (presumably #144673) made this pull request unmergeable. Please resolve the merge conflicts. |
ca9c162 to
5490a8c
Compare
|
Some changes occurred in compiler/rustc_hir/src/attrs
|
This comment has been minimized.
This comment has been minimized.
5490a8c to
c74b369
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
c74b369 to
290c4df
Compare
|
☔ The latest upstream changes (presumably #148356) made this pull request unmergeable. Please resolve the merge conflicts. |
…jorn3
Add `#[rustc_pass_indirectly_in_non_rustic_abis]`
This PR adds an internal `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute that can be applied to structs. Structs marked with this attribute will always be passed using `PassMode::Indirect { on_stack: false, .. }` when being passed by value to functions with non-Rustic calling conventions. This is needed by rust-lang#141980; see that PR for further details.
cc `@joshtriplett`
…jorn3
Add `#[rustc_pass_indirectly_in_non_rustic_abis]`
This PR adds an internal `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute that can be applied to structs. Structs marked with this attribute will always be passed using `PassMode::Indirect { on_stack: false, .. }` when being passed by value to functions with non-Rustic calling conventions. This is needed by rust-lang#141980; see that PR for further details.
cc ``@joshtriplett``
…jorn3
Add `#[rustc_pass_indirectly_in_non_rustic_abis]`
This PR adds an internal `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute that can be applied to structs. Structs marked with this attribute will always be passed using `PassMode::Indirect { on_stack: false, .. }` when being passed by value to functions with non-Rustic calling conventions. This is needed by rust-lang#141980; see that PR for further details.
cc `@joshtriplett`
Add `#[rustc_pass_indirectly_in_non_rustic_abis]`
This PR adds an internal `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute that can be applied to structs. Structs marked with this attribute will always be passed using `PassMode::Indirect { on_stack: false, .. }` when being passed by value to functions with non-Rustic calling conventions. This is needed by #141980; see that PR for further details.
cc `@joshtriplett`
Rollup merge of #144529 - beetrees:pass-indirectly-attr, r=bjorn3 Add `#[rustc_pass_indirectly_in_non_rustic_abis]` This PR adds an internal `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute that can be applied to structs. Structs marked with this attribute will always be passed using `PassMode::Indirect { on_stack: false, .. }` when being passed by value to functions with non-Rustic calling conventions. This is needed by #141980; see that PR for further details. cc `@joshtriplett`
290c4df to
e68ffaa
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
| // The fallback implementation, used for: | ||
| // | ||
| // - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599) | ||
| // - windows | ||
| // - powerpc64 & powerpc64le | ||
| // - uefi | ||
| // - any other target for which we don't specify the `VaListImpl` above | ||
| // - any other target for which we don't specify the `VaListInner` above | ||
| // | ||
| // In this implementation the `va_list` type is just an alias for an opaque pointer. | ||
| // That pointer is probably just the next variadic argument on the caller's stack. | ||
| _ => { | ||
| /// Basic implementation of a `va_list`. |
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.
How do we feel about this wildcard match? Is it feasible to instead list the targets for which we actually know that they use an opaque pointer, and fail to build for any other targets?
Being exhaustive may create some churn, but at least we'll then never miscompile for a target that we did not consider.
tracking issue: #44930
related PR: #144529
On some platforms, the C
va_listtype is actually a single-element array of a struct (on other platforms it is just a pointer). In C, arrays passed as function arguments expirience array-to-pointer decay, which means that C will pass a pointer to the array in the caller instead of the array itself, and modifications to the array in the callee will be visible to the caller (this does not match Rust by-value semantics). However, forva_list, the C standard explicitly states that it is undefined behaviour to use ava_listafter it has been passed by value to a function (in Rust parlance, theva_listis moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the Cva_listtype is a single-element array of a struct, the ABI will match C as long as the Rust type is always be passed indirectly.In the old implementation, this ABI was achieved by having two separate types:
VaListwas the type that needed to be used when passing aVaListas a function parameter, whereasVaListImplwas the actualva_listtype that was correct everywhere else. This however is quite confusing, as there are lots of footguns: it is easy to cause bugs by mixing them up (e.g. the C functionvoid foo(va_list va)was equivalent to the Rustfn foo(va: VaList)whereas the C functionvoid bar(va_list* va)was equivalent to the Rustfn foo(va: *mut VaListImpl), notfn foo(va: *mut VaList)as might be expected); also converting fromVaListImpltoVaListwithas_va_list()had platform specific behaviour: on single-element array of a struct platforms it would return aVaListreferencing the originalVaListImpl, whereas on other platforms it would return a cioy,In this PR, there is now just a single
VaListtype (renamed fromVaListImpl) which represents the Cva_listtype and will just work in all positions. Instead of having a separate type just to make the ABI work, #144529 adds a#[rustc_pass_indirectly_in_non_rustic_abis]attribute, which when applied to a struct will force the struct to be passed indirectly by non-Rustic calling conventions. This PR then implements theVaListrework, making use of the new attribute on all platforms where the Cva_listtype is a single-element array of a struct.Cleanup of the
VaListAPI and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not callingva_endis not undefined behaviour (#141524 (comment)), I've removed thewith_copymethod as it was redundant to theCloneimpl (theDropimpl ofVaListis a no-op asva_endis a no-op on all known platforms).Previous discussion: #141524 and t-compiler > c_variadic API and ABI
Tracking issue: #44930
r? @joshtriplett