1use crate::ffi::c_void;
6#[allow(unused_imports)]
7use crate::fmt;
8use crate::marker::PhantomData;
9use crate::ops::{Deref, DerefMut};
10
11#[cfg(any(
14 all(
15 not(target_arch = "aarch64"),
16 not(target_arch = "powerpc"),
17 not(target_arch = "s390x"),
18 not(target_arch = "xtensa"),
19 not(target_arch = "x86_64")
20 ),
21 all(target_arch = "aarch64", target_vendor = "apple"),
22 target_family = "wasm",
23 target_os = "uefi",
24 windows,
25))]
26#[repr(transparent)]
27#[lang = "va_list"]
28pub struct VaListImpl<'f> {
29 ptr: *mut c_void,
30
31 _marker: PhantomData<&'f mut &'f c_void>,
34}
35
36#[cfg(any(
37 all(
38 not(target_arch = "aarch64"),
39 not(target_arch = "powerpc"),
40 not(target_arch = "s390x"),
41 not(target_arch = "xtensa"),
42 not(target_arch = "x86_64")
43 ),
44 all(target_arch = "aarch64", target_vendor = "apple"),
45 target_family = "wasm",
46 target_os = "uefi",
47 windows,
48))]
49impl<'f> fmt::Debug for VaListImpl<'f> {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "va_list* {:p}", self.ptr)
52 }
53}
54
55#[cfg(all(
61 target_arch = "aarch64",
62 not(target_vendor = "apple"),
63 not(target_os = "uefi"),
64 not(windows),
65))]
66#[cfg_attr(not(doc), repr(C))] #[derive(Debug)]
68#[lang = "va_list"]
69pub struct VaListImpl<'f> {
70 stack: *mut c_void,
71 gr_top: *mut c_void,
72 vr_top: *mut c_void,
73 gr_offs: i32,
74 vr_offs: i32,
75 _marker: PhantomData<&'f mut &'f c_void>,
76}
77
78#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
80#[cfg_attr(not(doc), repr(C))] #[derive(Debug)]
82#[lang = "va_list"]
83pub struct VaListImpl<'f> {
84 gpr: u8,
85 fpr: u8,
86 reserved: u16,
87 overflow_arg_area: *mut c_void,
88 reg_save_area: *mut c_void,
89 _marker: PhantomData<&'f mut &'f c_void>,
90}
91
92#[cfg(target_arch = "s390x")]
94#[cfg_attr(not(doc), repr(C))] #[derive(Debug)]
96#[lang = "va_list"]
97pub struct VaListImpl<'f> {
98 gpr: i64,
99 fpr: i64,
100 overflow_arg_area: *mut c_void,
101 reg_save_area: *mut c_void,
102 _marker: PhantomData<&'f mut &'f c_void>,
103}
104
105#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
107#[cfg_attr(not(doc), repr(C))] #[derive(Debug)]
109#[lang = "va_list"]
110pub struct VaListImpl<'f> {
111 gp_offset: i32,
112 fp_offset: i32,
113 overflow_arg_area: *mut c_void,
114 reg_save_area: *mut c_void,
115 _marker: PhantomData<&'f mut &'f c_void>,
116}
117
118#[cfg(target_arch = "xtensa")]
120#[repr(C)]
121#[derive(Debug)]
122#[lang = "va_list"]
123pub struct VaListImpl<'f> {
124 stk: *mut i32,
125 reg: *mut i32,
126 ndx: i32,
127 _marker: PhantomData<&'f mut &'f c_void>,
128}
129
130#[repr(transparent)]
132#[derive(Debug)]
133pub struct VaList<'a, 'f: 'a> {
134 #[cfg(any(
135 all(
136 not(target_arch = "aarch64"),
137 not(target_arch = "powerpc"),
138 not(target_arch = "s390x"),
139 not(target_arch = "x86_64")
140 ),
141 target_arch = "xtensa",
142 all(target_arch = "aarch64", target_vendor = "apple"),
143 target_family = "wasm",
144 target_os = "uefi",
145 windows,
146 ))]
147 inner: VaListImpl<'f>,
148
149 #[cfg(all(
150 any(
151 target_arch = "aarch64",
152 target_arch = "powerpc",
153 target_arch = "s390x",
154 target_arch = "x86_64"
155 ),
156 not(target_arch = "xtensa"),
157 any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
158 not(target_family = "wasm"),
159 not(target_os = "uefi"),
160 not(windows),
161 ))]
162 inner: &'a mut VaListImpl<'f>,
163
164 _marker: PhantomData<&'a mut VaListImpl<'f>>,
165}
166
167#[cfg(any(
168 all(
169 not(target_arch = "aarch64"),
170 not(target_arch = "powerpc"),
171 not(target_arch = "s390x"),
172 not(target_arch = "x86_64")
173 ),
174 target_arch = "xtensa",
175 all(target_arch = "aarch64", target_vendor = "apple"),
176 target_family = "wasm",
177 target_os = "uefi",
178 windows,
179))]
180impl<'f> VaListImpl<'f> {
181 #[inline]
183 pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
184 VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
185 }
186}
187
188#[cfg(all(
189 any(
190 target_arch = "aarch64",
191 target_arch = "powerpc",
192 target_arch = "s390x",
193 target_arch = "xtensa",
194 target_arch = "x86_64"
195 ),
196 not(target_arch = "xtensa"),
197 any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
198 not(target_family = "wasm"),
199 not(target_os = "uefi"),
200 not(windows),
201))]
202impl<'f> VaListImpl<'f> {
203 #[inline]
205 pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
206 VaList { inner: self, _marker: PhantomData }
207 }
208}
209
210impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
211 type Target = VaListImpl<'f>;
212
213 #[inline]
214 fn deref(&self) -> &VaListImpl<'f> {
215 &self.inner
216 }
217}
218
219impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
220 #[inline]
221 fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
222 &mut self.inner
223 }
224}
225
226mod sealed {
227 pub trait Sealed {}
228
229 impl Sealed for i32 {}
230 impl Sealed for i64 {}
231 impl Sealed for isize {}
232
233 impl Sealed for u32 {}
234 impl Sealed for u64 {}
235 impl Sealed for usize {}
236
237 impl Sealed for f64 {}
238
239 impl<T> Sealed for *mut T {}
240 impl<T> Sealed for *const T {}
241}
242
243pub unsafe trait VaArgSafe: sealed::Sealed {}
256
257unsafe impl VaArgSafe for i32 {}
259unsafe impl VaArgSafe for i64 {}
260unsafe impl VaArgSafe for isize {}
261
262unsafe impl VaArgSafe for u32 {}
264unsafe impl VaArgSafe for u64 {}
265unsafe impl VaArgSafe for usize {}
266
267unsafe impl VaArgSafe for f64 {}
269
270unsafe impl<T> VaArgSafe for *mut T {}
271unsafe impl<T> VaArgSafe for *const T {}
272
273impl<'f> VaListImpl<'f> {
274 #[inline]
276 pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
277 unsafe { va_arg(self) }
279 }
280
281 pub unsafe fn with_copy<F, R>(&self, f: F) -> R
283 where
284 F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
285 {
286 let mut ap = self.clone();
287 let ret = f(ap.as_va_list());
288 unsafe {
290 va_end(&mut ap);
291 }
292 ret
293 }
294}
295
296impl<'f> Clone for VaListImpl<'f> {
297 #[inline]
298 fn clone(&self) -> Self {
299 let mut dest = crate::mem::MaybeUninit::uninit();
300 unsafe {
302 va_copy(dest.as_mut_ptr(), self);
303 dest.assume_init()
304 }
305 }
306}
307
308impl<'f> Drop for VaListImpl<'f> {
309 fn drop(&mut self) {
310 }
321}
322
323#[rustc_intrinsic]
326#[rustc_nounwind]
327unsafe fn va_end(ap: &mut VaListImpl<'_>);
328
329#[rustc_intrinsic]
331#[rustc_nounwind]
332unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
333
334#[rustc_intrinsic]
337#[rustc_nounwind]
338unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;