use cfg_select! to select the right VaListImpl definition

This commit is contained in:
Folkert de Vries 2025-05-21 19:18:31 +02:00
parent 6eef33bb39
commit 89a8abc4be
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -5,148 +5,120 @@
use crate::ffi::c_void;
#[allow(unused_imports)]
use crate::fmt;
use crate::marker::PhantomData;
use crate::marker::{PhantomData, PhantomInvariantLifetime};
use crate::ops::{Deref, DerefMut};
/// Basic implementation of a `va_list`.
// The name is WIP, using `VaListImpl` for now.
#[cfg(any(
//
// Most targets explicitly specify the layout of `va_list`, this layout is matched here.
crate::cfg_select! {
all(
not(target_arch = "aarch64"),
not(target_arch = "powerpc"),
not(target_arch = "s390x"),
not(target_arch = "xtensa"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", target_vendor = "apple"),
target_family = "wasm",
target_os = "uefi",
windows,
))]
#[repr(transparent)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
ptr: *mut c_void,
target_arch = "aarch64",
not(target_vendor = "apple"),
not(target_os = "uefi"),
not(windows),
) => {
/// AArch64 ABI implementation of a `va_list`. See the
/// [AArch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
stack: *mut c_void,
gr_top: *mut c_void,
vr_top: *mut c_void,
gr_offs: i32,
vr_offs: i32,
_marker: PhantomInvariantLifetime<'f>,
}
}
all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => {
/// PowerPC ABI implementation of a `va_list`.
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gpr: u8,
fpr: u8,
reserved: u16,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomInvariantLifetime<'f>,
}
}
target_arch = "s390x" => {
/// s390x ABI implementation of a `va_list`.
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gpr: i64,
fpr: i64,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomInvariantLifetime<'f>,
}
}
all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => {
/// x86_64 ABI implementation of a `va_list`.
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gp_offset: i32,
fp_offset: i32,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomInvariantLifetime<'f>,
}
}
target_arch = "xtensa" => {
/// Xtensa ABI implementation of a `va_list`.
#[repr(C)]
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
stk: *mut i32,
reg: *mut i32,
ndx: i32,
_marker: PhantomInvariantLifetime<'f>,
}
}
// Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
// the region of the function it's defined in
_marker: PhantomData<&'f mut &'f c_void>,
}
// The fallback implementation, used for:
//
// - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599)
// - windows
// - uefi
// - any other target for which we don't specify the `VaListImpl` 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`.
#[repr(transparent)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
ptr: *mut c_void,
#[cfg(any(
all(
not(target_arch = "aarch64"),
not(target_arch = "powerpc"),
not(target_arch = "s390x"),
not(target_arch = "xtensa"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", target_vendor = "apple"),
target_family = "wasm",
target_os = "uefi",
windows,
))]
impl<'f> fmt::Debug for VaListImpl<'f> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "va_list* {:p}", self.ptr)
// Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
// the region of the function it's defined in
_marker: PhantomInvariantLifetime<'f>,
}
impl<'f> fmt::Debug for VaListImpl<'f> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "va_list* {:p}", self.ptr)
}
}
}
}
/// AArch64 ABI implementation of a `va_list`. See the
/// [AArch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(
target_arch = "aarch64",
not(target_vendor = "apple"),
not(target_os = "uefi"),
not(windows),
))]
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
stack: *mut c_void,
gr_top: *mut c_void,
vr_top: *mut c_void,
gr_offs: i32,
vr_offs: i32,
_marker: PhantomData<&'f mut &'f c_void>,
}
/// PowerPC ABI implementation of a `va_list`.
#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gpr: u8,
fpr: u8,
reserved: u16,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomData<&'f mut &'f c_void>,
}
/// s390x ABI implementation of a `va_list`.
#[cfg(target_arch = "s390x")]
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gpr: i64,
fpr: i64,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomData<&'f mut &'f c_void>,
}
/// x86_64 ABI implementation of a `va_list`.
#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gp_offset: i32,
fp_offset: i32,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomData<&'f mut &'f c_void>,
}
/// Xtensa ABI implementation of a `va_list`.
#[cfg(target_arch = "xtensa")]
#[repr(C)]
#[derive(Debug)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
stk: *mut i32,
reg: *mut i32,
ndx: i32,
_marker: PhantomData<&'f mut &'f c_void>,
}
/// A wrapper for a `va_list`
#[repr(transparent)]
#[derive(Debug)]
pub struct VaList<'a, 'f: 'a> {
#[cfg(any(
all(
not(target_arch = "aarch64"),
not(target_arch = "powerpc"),
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
target_arch = "xtensa",
all(target_arch = "aarch64", target_vendor = "apple"),
target_family = "wasm",
target_os = "uefi",
windows,
))]
inner: VaListImpl<'f>,
#[cfg(all(
crate::cfg_select! {
all(
any(
target_arch = "aarch64",
target_arch = "powerpc",
@ -158,52 +130,41 @@ pub struct VaList<'a, 'f: 'a> {
not(target_family = "wasm"),
not(target_os = "uefi"),
not(windows),
))]
inner: &'a mut VaListImpl<'f>,
) => {
/// A wrapper for a `va_list`
#[repr(transparent)]
#[derive(Debug)]
pub struct VaList<'a, 'f: 'a> {
inner: &'a mut VaListImpl<'f>,
_marker: PhantomData<&'a mut VaListImpl<'f>>,
}
_marker: PhantomData<&'a mut VaListImpl<'f>>,
}
#[cfg(any(
all(
not(target_arch = "aarch64"),
not(target_arch = "powerpc"),
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
target_arch = "xtensa",
all(target_arch = "aarch64", target_vendor = "apple"),
target_family = "wasm",
target_os = "uefi",
windows,
))]
impl<'f> VaListImpl<'f> {
/// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
impl<'f> VaListImpl<'f> {
/// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: self, _marker: PhantomData }
}
}
}
}
#[cfg(all(
any(
target_arch = "aarch64",
target_arch = "powerpc",
target_arch = "s390x",
target_arch = "xtensa",
target_arch = "x86_64"
),
not(target_arch = "xtensa"),
any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
not(target_family = "wasm"),
not(target_os = "uefi"),
not(windows),
))]
impl<'f> VaListImpl<'f> {
/// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: self, _marker: PhantomData }
_ => {
/// A wrapper for a `va_list`
#[repr(transparent)]
#[derive(Debug)]
pub struct VaList<'a, 'f: 'a> {
inner: VaListImpl<'f>,
_marker: PhantomData<&'a mut VaListImpl<'f>>,
}
impl<'f> VaListImpl<'f> {
/// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
}
}
}
}