-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Add #[rustc_pass_indirectly_in_non_rustic_abis]
#144529
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
Conversation
|
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
|
Some changes occurred in compiler/rustc_attr_data_structures Some changes occurred in compiler/rustc_attr_parsing Some changes occurred in compiler/rustc_passes/src/check_attr.rs |
| Ty: TyAbiInterface<'a, C> + Copy, | ||
| C: HasDataLayout, | ||
| { | ||
| if arg.layout.pass_indirectly_in_non_rustic_abis(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.
If we rely on every single callconv getting this right, we're toast. It's way too easy to forget this somewhere.
Is there some way we can do this centrally for all ABIs?
For instance, we could apply this logic after the target-specific ABI stuff has been done.
Cc @workingjubilee
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 individual calling conventions sometimes still need to be aware of the parameters, to update the number of remaining general-purpose registers, and the current design of the calling convention code makes it hard to abstract this. Separately from this PR, I've been planning to refactor the calling convention handling a bit as even without this change there's a lot of code duplication already (all the compute_abi_info functions are essentially variants of the same function with calls to classify_arg and classify_ret); this refactoring should make it possible to do this in a more centralised way.
For now, this PR previously had a cfg!(debug_assertions)-guarded check at the end of adjust_for_foreign_abi in callconv/mod.rs that asserts that individual calling convention correctly set all the #[rustc_pass_indirectly_in_non_rustic_abis] arguments to be passed indirectly. I've updated the check so it now always run rather than just running when debug_assetions are enabled.
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 individual calling conventions sometimes still need to be aware of the parameters, to update the number of remaining general-purpose registers,
Urgh, right, I forgot we need to care about low-level nonsense like that here. :/
Regarding refactoring the ABI code, also see #119183. I think @workingjubilee also has some thoughts in that direction. I'm happy to discuss design options and provide feedback.
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.
Not the most robust idea, but we there could be some kind of ICE-causing bomb that gets defused when checking an arg's pass_indirectly_in_non_rustic_abis and ignored if there are no args. This at least makes sure that new targets don't get very far if they miss this important detail.
Or a codegen test that gets run on all 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.
We have some code doing sanity checks on the ABI after it got computed. We could probably add an assertion there.
rust/compiler/rustc_ty_utils/src/abi.rs
Lines 368 to 372 in d71ed8d
| fn fn_abi_sanity_check<'tcx>( | |
| cx: &LayoutCx<'tcx>, | |
| fn_abi: &FnAbi<'tcx, Ty<'tcx>>, | |
| spec_abi: ExternAbi, | |
| ) { |
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 indirect_argument function would not be codegened if it doesn't get called, so that wouldn't trigger the ABI check. It should probably just be a ui test. This won't run in CI for tier 3 targets, but the worst that can happen is that you get an ICE, not a silent miscompilation.
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 make sure that triggers for every ABI though?
It's an unstable attribute, so worst case we get an ICE when building libcore. That seems fine.
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 indirect_argument function would not be codegened if it doesn't get called, so that wouldn't trigger the ABI check.
what if we use a const fn? Maybe using some const _: () = assert!(/* ... */), would that work?
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.
Using const does work, I added that and a fix for transparent wrappers ignoring the attribute at master...folkertdev:rust:pass-indirectly-attr-updates
@beetrees feel free to steal or chery-pick from that. I'd also happily force-push to this branch if you don't have time/interest. (this is on the critical path for c-variadics now that the error messages are in a good state, and I'd hate to waste the reviewer momentum).
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've cherry-picked your patch for this.
c0357c1 to
61196cb
Compare
|
@jdonszelmann could you have a look at the attribute code here? This is my first time actually seeing the new infrastructure so I can't say if the way it is used here is correct. |
RalfJung
left a comment
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 compiler part LGTM apart from these comments, but I can't really review these ABI adjustments.
61196cb to
ed746a3
Compare
|
☔ The latest upstream changes (presumably #144740) made this pull request unmergeable. Please resolve the merge conflicts. |
ed746a3 to
d91160a
Compare
|
Some changes occurred in compiler/rustc_hir/src/attrs |
This comment has been minimized.
This comment has been minimized.
d91160a to
0401bf3
Compare
|
r? @joshtriplett :) |
|
|
0401bf3 to
b8bd968
Compare
This comment has been minimized.
This comment has been minimized.
|
Besides Jubilee, who is not available, the only other person I can think of to review ABI code is r? @bjorn3 |
|
☔ The latest upstream changes (presumably #146360) made this pull request unmergeable. Please resolve the merge conflicts. |
b8bd968 to
1953e54
Compare
This comment has been minimized.
This comment has been minimized.
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`
|
Yielding to enclosing rollup. @bors retry |
Rollup of 4 pull requests Successful merges: - #144529 (Add `#[rustc_pass_indirectly_in_non_rustic_abis]`) - #147017 (FCW for repr(C) enums whose discriminant values do not fit into a c_int or c_uint) - #148459 (bootstrap: Split out a separate `./x test bootstrap-py` step) - #148468 (add logging to `fudge_inference_if_ok`) r? `@ghost` `@rustbot` modify labels: rollup
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`
error on non-rustic ABIs using unsized parameters tracking issue: #48055 This came up in #144529 (comment). The idea is that the layout of an unsized type is unstable (following the rust layout rules), and hence stable ABIs should not use unsized types. On stable, unsized types (or generics with a `?Sized` bound) are not accepted as parameters, so the errors introduced by this PR can only be observed when the unstable `unsized_fn_params` feature is enabled. r? `@bjorn3` cc `@RalfJung`
|
Perf results show a few regressions in |
error on non-rustic ABIs using unsized parameters tracking issue: #48055 This came up in #144529 (comment). The idea is that the layout of an unsized type is unstable (following the rust layout rules), and hence stable ABIs should not use unsized types. On stable, unsized types (or generics with a `?Sized` bound) are not accepted as parameters, so the errors introduced by this PR can only be observed when the unstable `unsized_fn_params` feature is enabled. r? `@bjorn3` cc `@RalfJung`
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 should I evaluate that regression? There is one minor optimization in a comment below, but beyond that I think the cost is additional queries for the attribute flag, and that is impossible to work around I think (plus should be mostly cached).
|
|
||
| // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. | ||
| if find_attr!( | ||
| self.get_all_attrs(did), |
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 could be re-used from earlier
|
I thought the regression looked real, but the same benchmarks bounced back in #148507 (comment), so maybe it’s noise? |
|
@folkertdev please feel free to submit the PR and we can run perf to see if it matters. |
…ttrs, r=JonathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? `@JonathanBrouwer` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…ttrs, r=JonathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ``@JonathanBrouwer`` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…ttrs, r=JonathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ```@JonathanBrouwer``` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…ttrs, r=JonathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ````@JonathanBrouwer```` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
Rollup merge of #148600 - folkertdev:pass-indirectly-reuse-attrs, r=JonathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here #144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ````@JonathanBrouwer```` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…onathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang/rust#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ````@JonathanBrouwer```` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…onathanBrouwer re-use `self.get_all_attrs` result for pass indirectly attribute Could be a fix for a potential performance regression reported here rust-lang/rust#144529 (comment). Apparently the regression later disappeared. Nevertheless, this seems like a decent refactor. r? ````@JonathanBrouwer```` (vaguely attribute-related, maybe there are other optimizations to that PR that we're missing)
…ngjubilee Rework `c_variadic` tracking issue: rust-lang#44930 related PR: rust-lang#144529 On some platforms, the C `va_list` type 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, for `va_list`, the C standard explicitly states that it is undefined behaviour to use a `va_list` after it has been passed by value to a function (in Rust parlance, the `va_list` is moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the C `va_list` type 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: `VaList` was the type that needed to be used when passing a `VaList` as a function parameter, whereas `VaListImpl` was the actual `va_list` type 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 function `void foo(va_list va)` was equivalent to the Rust `fn foo(va: VaList)` whereas the C function `void bar(va_list* va)` was equivalent to the Rust `fn foo(va: *mut VaListImpl)`, not `fn foo(va: *mut VaList)` as might be expected); also converting from `VaListImpl` to `VaList` with `as_va_list()` had platform specific behaviour: on single-element array of a struct platforms it would return a `VaList` referencing the original `VaListImpl`, whereas on other platforms it would return a cioy, In this PR, there is now just a single `VaList` type (renamed from `VaListImpl`) which represents the C `va_list` type and will just work in all positions. Instead of having a separate type just to make the ABI work, rust-lang#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 the `VaList` rework, making use of the new attribute on all platforms where the C `va_list` type is a single-element array of a struct. Cleanup of the `VaList` API and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not calling `va_end` is not undefined behaviour (rust-lang#141524 (comment)), I've removed the `with_copy` method as it was redundant to the `Clone` impl (the `Drop` impl of `VaList` is a no-op as `va_end` is a no-op on all known platforms). Previous discussion: rust-lang#141524 and [t-compiler > c_variadic API and ABI](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/c_variadic.20API.20and.20ABI) Tracking issue: rust-lang#44930 r? `@joshtriplett`
Rework `c_variadic` tracking issue: #44930 related PR: #144529 On some platforms, the C `va_list` type 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, for `va_list`, the C standard explicitly states that it is undefined behaviour to use a `va_list` after it has been passed by value to a function (in Rust parlance, the `va_list` is moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the C `va_list` type 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: `VaList` was the type that needed to be used when passing a `VaList` as a function parameter, whereas `VaListImpl` was the actual `va_list` type 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 function `void foo(va_list va)` was equivalent to the Rust `fn foo(va: VaList)` whereas the C function `void bar(va_list* va)` was equivalent to the Rust `fn foo(va: *mut VaListImpl)`, not `fn foo(va: *mut VaList)` as might be expected); also converting from `VaListImpl` to `VaList` with `as_va_list()` had platform specific behaviour: on single-element array of a struct platforms it would return a `VaList` referencing the original `VaListImpl`, whereas on other platforms it would return a cioy, In this PR, there is now just a single `VaList` type (renamed from `VaListImpl`) which represents the C `va_list` type 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 the `VaList` rework, making use of the new attribute on all platforms where the C `va_list` type is a single-element array of a struct. Cleanup of the `VaList` API and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not calling `va_end` is not undefined behaviour (#141524 (comment)), I've removed the `with_copy` method as it was redundant to the `Clone` impl (the `Drop` impl of `VaList` is a no-op as `va_end` is a no-op on all known platforms). Previous discussion: #141524 and [t-compiler > c_variadic API and ABI](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/c_variadic.20API.20and.20ABI) Tracking issue: #44930 r? `@joshtriplett`
…ngjubilee Rework `c_variadic` tracking issue: rust-lang#44930 related PR: rust-lang#144529 On some platforms, the C `va_list` type 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, for `va_list`, the C standard explicitly states that it is undefined behaviour to use a `va_list` after it has been passed by value to a function (in Rust parlance, the `va_list` is moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the C `va_list` type 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: `VaList` was the type that needed to be used when passing a `VaList` as a function parameter, whereas `VaListImpl` was the actual `va_list` type 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 function `void foo(va_list va)` was equivalent to the Rust `fn foo(va: VaList)` whereas the C function `void bar(va_list* va)` was equivalent to the Rust `fn foo(va: *mut VaListImpl)`, not `fn foo(va: *mut VaList)` as might be expected); also converting from `VaListImpl` to `VaList` with `as_va_list()` had platform specific behaviour: on single-element array of a struct platforms it would return a `VaList` referencing the original `VaListImpl`, whereas on other platforms it would return a cioy, In this PR, there is now just a single `VaList` type (renamed from `VaListImpl`) which represents the C `va_list` type and will just work in all positions. Instead of having a separate type just to make the ABI work, rust-lang#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 the `VaList` rework, making use of the new attribute on all platforms where the C `va_list` type is a single-element array of a struct. Cleanup of the `VaList` API and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not calling `va_end` is not undefined behaviour (rust-lang#141524 (comment)), I've removed the `with_copy` method as it was redundant to the `Clone` impl (the `Drop` impl of `VaList` is a no-op as `va_end` is a no-op on all known platforms). Previous discussion: rust-lang#141524 and [t-compiler > c_variadic API and ABI](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/c_variadic.20API.20and.20ABI) Tracking issue: rust-lang#44930 r? `@joshtriplett`
…ngjubilee Rework `c_variadic` tracking issue: rust-lang#44930 related PR: rust-lang#144529 On some platforms, the C `va_list` type 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, for `va_list`, the C standard explicitly states that it is undefined behaviour to use a `va_list` after it has been passed by value to a function (in Rust parlance, the `va_list` is moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the C `va_list` type 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: `VaList` was the type that needed to be used when passing a `VaList` as a function parameter, whereas `VaListImpl` was the actual `va_list` type 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 function `void foo(va_list va)` was equivalent to the Rust `fn foo(va: VaList)` whereas the C function `void bar(va_list* va)` was equivalent to the Rust `fn foo(va: *mut VaListImpl)`, not `fn foo(va: *mut VaList)` as might be expected); also converting from `VaListImpl` to `VaList` with `as_va_list()` had platform specific behaviour: on single-element array of a struct platforms it would return a `VaList` referencing the original `VaListImpl`, whereas on other platforms it would return a cioy, In this PR, there is now just a single `VaList` type (renamed from `VaListImpl`) which represents the C `va_list` type and will just work in all positions. Instead of having a separate type just to make the ABI work, rust-lang#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 the `VaList` rework, making use of the new attribute on all platforms where the C `va_list` type is a single-element array of a struct. Cleanup of the `VaList` API and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not calling `va_end` is not undefined behaviour (rust-lang#141524 (comment)), I've removed the `with_copy` method as it was redundant to the `Clone` impl (the `Drop` impl of `VaList` is a no-op as `va_end` is a no-op on all known platforms). Previous discussion: rust-lang#141524 and [t-compiler > c_variadic API and ABI](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/c_variadic.20API.20and.20ABI) Tracking issue: rust-lang#44930 r? ``@joshtriplett``
…ngjubilee Rework `c_variadic` tracking issue: rust-lang#44930 related PR: rust-lang#144529 On some platforms, the C `va_list` type 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, for `va_list`, the C standard explicitly states that it is undefined behaviour to use a `va_list` after it has been passed by value to a function (in Rust parlance, the `va_list` is moved, not copied). This matches Rust's pass-by-value semantics, meaning that when the C `va_list` type 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: `VaList` was the type that needed to be used when passing a `VaList` as a function parameter, whereas `VaListImpl` was the actual `va_list` type 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 function `void foo(va_list va)` was equivalent to the Rust `fn foo(va: VaList)` whereas the C function `void bar(va_list* va)` was equivalent to the Rust `fn foo(va: *mut VaListImpl)`, not `fn foo(va: *mut VaList)` as might be expected); also converting from `VaListImpl` to `VaList` with `as_va_list()` had platform specific behaviour: on single-element array of a struct platforms it would return a `VaList` referencing the original `VaListImpl`, whereas on other platforms it would return a cioy, In this PR, there is now just a single `VaList` type (renamed from `VaListImpl`) which represents the C `va_list` type and will just work in all positions. Instead of having a separate type just to make the ABI work, rust-lang#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 the `VaList` rework, making use of the new attribute on all platforms where the C `va_list` type is a single-element array of a struct. Cleanup of the `VaList` API and implementation is also included in this PR: since it was decided it was OK to experiment with Rust requiring that not calling `va_end` is not undefined behaviour (rust-lang#141524 (comment)), I've removed the `with_copy` method as it was redundant to the `Clone` impl (the `Drop` impl of `VaList` is a no-op as `va_end` is a no-op on all known platforms). Previous discussion: rust-lang#141524 and [t-compiler > c_variadic API and ABI](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/c_variadic.20API.20and.20ABI) Tracking issue: rust-lang#44930 r? ```@joshtriplett```
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 usingPassMode::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