Skip to content

Commit 764e35f

Browse files
committed
document VaList ABI for more targets
1 parent b8dda2a commit 764e35f

File tree

1 file changed

+49
-8
lines changed

1 file changed

+49
-8
lines changed

library/core/src/ffi/va_list.rs

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,39 @@ use crate::fmt;
88
use crate::intrinsics::{va_arg, va_copy};
99
use crate::marker::PhantomCovariantLifetime;
1010

11-
// Most targets explicitly specify the layout of `va_list`, this layout is matched here.
12-
// For `va_list`s which are single-element array in C (and therefore experience array-to-pointer
13-
// decay when passed as arguments in C), the `VaList` struct is annotated with
14-
// `#[rustc_pass_indirectly_in_non_rustic_abis]`. This ensures that the compiler uses the correct
15-
// ABI for functions like `extern "C" fn takes_va_list(va: VaList<'_>)` by passing `va` indirectly.
11+
// There are currently three flavors of how a C `va_list` is implemented for
12+
// targets that Rust supports:
13+
//
14+
// - `va_list` is an opaque pointer
15+
// - `va_list` is a struct
16+
// - `va_list` is a single-element array, containing a struct
17+
//
18+
// The opaque pointer approach is the simplest to implement: the pointer just
19+
// points to an array of arguments on the caller's stack.
20+
//
21+
// The struct and single-element array variants are more complex, but
22+
// potentially more efficient because the additional state makes it
23+
// possible to pass variadic arguments via registers.
24+
//
25+
// The Rust `VaList` type is ABI-compatible with the C `va_list`.
26+
// The struct and pointer cases straightforwardly map to their rust equivalents,
27+
// but the single-element array case is special: in C, this type is subject to
28+
// array-to-pointer decay.
29+
//
30+
// The `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute is used to match
31+
// the pointer decay behavior in Rust. This attribute ensures that the compiler
32+
// uses the correct ABI for functions like
33+
// `extern "C" fn takes_va_list(va: VaList<'_>)` by passing `va` indirectly.
1634
crate::cfg_select! {
1735
all(
1836
target_arch = "aarch64",
1937
not(target_vendor = "apple"),
2038
not(target_os = "uefi"),
2139
not(windows),
2240
) => {
23-
/// AArch64 ABI implementation of a `va_list`. See the
24-
/// [AArch64 Procedure Call Standard] for more details.
41+
/// AArch64 ABI implementation of a `va_list`.
42+
///
43+
/// See the [AArch64 Procedure Call Standard] for more details.
2544
///
2645
/// [AArch64 Procedure Call Standard]:
2746
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
@@ -37,6 +56,12 @@ crate::cfg_select! {
3756
}
3857
all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => {
3958
/// PowerPC ABI implementation of a `va_list`.
59+
///
60+
/// See the [LLVM source] and [GCC header] for more details.
61+
///
62+
/// [LLVM source]:
63+
/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/PowerPC/PPCISelLowering.cpp#L4089-L4111
64+
/// [GCC header]: https://web.mit.edu/darwin/src/modules/gcc/gcc/ginclude/va-ppc.h
4065
#[repr(C)]
4166
#[derive(Debug)]
4267
#[rustc_pass_indirectly_in_non_rustic_abis]
@@ -50,6 +75,11 @@ crate::cfg_select! {
5075
}
5176
target_arch = "s390x" => {
5277
/// s390x ABI implementation of a `va_list`.
78+
///
79+
/// See the [S/390x ELF Application Binary Interface Supplement] for more details.
80+
///
81+
/// [S/390x ELF Application Binary Interface Supplement]:
82+
/// https://docs.google.com/gview?embedded=true&url=https://github.com/IBM/s390x-abi/releases/download/v1.7/lzsabi_s390x.pdf
5383
#[repr(C)]
5484
#[derive(Debug)]
5585
#[rustc_pass_indirectly_in_non_rustic_abis]
@@ -61,7 +91,12 @@ crate::cfg_select! {
6191
}
6292
}
6393
all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => {
64-
/// x86_64 ABI implementation of a `va_list`.
94+
/// x86_64 System V ABI implementation of a `va_list`.
95+
///
96+
/// See the [System V AMD64 ABI] for more details.
97+
///
98+
/// [System V AMD64 ABI]:
99+
/// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
65100
#[repr(C)]
66101
#[derive(Debug)]
67102
#[rustc_pass_indirectly_in_non_rustic_abis]
@@ -74,6 +109,11 @@ crate::cfg_select! {
74109
}
75110
target_arch = "xtensa" => {
76111
/// Xtensa ABI implementation of a `va_list`.
112+
///
113+
/// See the [LLVM source] for more details.
114+
///
115+
/// [LLVM source]:
116+
/// https://github.com/llvm/llvm-project/blob/af9a4263a1a209953a1d339ef781a954e31268ff/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp#L1211-L1215
77117
#[repr(C)]
78118
#[derive(Debug)]
79119
#[rustc_pass_indirectly_in_non_rustic_abis]
@@ -88,6 +128,7 @@ crate::cfg_select! {
88128
//
89129
// - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599)
90130
// - windows
131+
// - powerpc64 & powerpc64le
91132
// - uefi
92133
// - any other target for which we don't specify the `VaListInner` above
93134
//

0 commit comments

Comments
 (0)