Skip to content

Commit 38324a1

Browse files
improve byval abi docs
1 parent c56ffaa commit 38324a1

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

Diff for: compiler/rustc_target/src/abi/call/mod.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,23 @@ pub enum PassMode {
4646
///
4747
/// The argument has a layout abi of `ScalarPair`.
4848
Pair(ArgAttributes, ArgAttributes),
49-
/// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
50-
/// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
49+
/// Pass the argument after casting it. See the `CastTarget` docs for details.
50+
///
51+
/// `pad_i32` indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
5152
Cast { pad_i32: bool, cast: Box<CastTarget> },
5253
/// Pass the argument indirectly via a hidden pointer.
54+
///
5355
/// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
5456
/// argument. (This is the only mode that supports unsized arguments.)
57+
///
5558
/// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
5659
/// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
57-
/// attribute (using a byte array type with the same size as the Rust type [which ensures that
58-
/// padding is preserved and that we do not rely on LLVM's struct layout], and with alignment
59-
/// determined in a complex, target-specific manner [see callers of `make_indirect_byval`]).
60+
/// attribute. The `byval` argument will use a byte array with the same size as the Rust type
61+
/// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout),
62+
/// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's
63+
/// alignment, depending on the target's ABI. This means that the alignment will not always
64+
/// match the Rust type's alignment; see documentation of `make_indirect_byval` for more info.
65+
///
6066
/// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`.
6167
Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
6268
}
@@ -598,6 +604,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
598604
}
599605
}
600606

607+
/// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
608+
/// This is valid for both sized and unsized arguments.
601609
pub fn make_indirect(&mut self) {
602610
match self.mode {
603611
PassMode::Direct(_) | PassMode::Pair(_, _) => {
@@ -611,7 +619,26 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
611619
}
612620
}
613621

622+
/// Pass this argument indirectly, by placing it at a fixed stack offset.
623+
/// This corresponds to the `byval` LLVM argument attribute.
624+
/// This is only valid for sized arguments.
625+
///
626+
/// `byval_align` specifies the alignment of the `byval` stack slot, which does not need to
627+
/// correspond to the type's alignment. This will be `Some` if the target's ABI specifies that
628+
/// stack slots used for arguments passed by-value have specific alignment requirements which
629+
/// differ from the alignment used in other situations.
630+
///
631+
/// If `None`, the type's alignment is used.
632+
///
633+
/// If the resulting alignment differs from the type's alignment,
634+
/// the argument will be copied to an alloca with sufficient alignment,
635+
/// either in the caller (if the type's alignment is lower than the byval alignment)
636+
/// or in the callee† (if the type's alignment is higher than the byval alignment),
637+
/// to ensure that Rust code never sees an underaligned pointer.
638+
///
639+
/// † This is currently broken, see <https://github.com/rust-lang/rust/pull/122212>.
614640
pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
641+
assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout");
615642
self.make_indirect();
616643
match self.mode {
617644
PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {

Diff for: compiler/rustc_target/src/abi/call/x86_64.rs

+2
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ where
217217
match cls_or_mem {
218218
Err(Memory) => {
219219
if is_arg {
220+
// The x86_64 ABI doesn't have any special requirements for `byval` alignment,
221+
// the type's alignment is always used.
220222
arg.make_indirect_byval(None);
221223
} else {
222224
// `sret` parameter thus one less integer register available

0 commit comments

Comments
 (0)