va_list/
impl-x86_64-elf.rs
1use ::core::{mem, ptr};
4use ::core::ffi::c_void;
5use super::VaPrimitive; #[repr(transparent)]
8pub struct VaList<'a>(&'a mut VaListInner);
9
10#[repr(C)]
11#[derive(Debug)]
12#[doc(hidden)]
13pub struct VaListInner {
14 gp_offset: u32,
15 fp_offset: u32,
16 overflow_arg_area: *const c_void,
17 reg_save_area: *const c_void,
18}
19
20impl<'a> VaList<'a> {
21 fn inner(&mut self) -> &mut VaListInner {
22 &mut *self.0
23 }
24}
25
26#[doc(hidden)]
27impl VaListInner {
28 fn check_space(&self, num_gp: u32, num_fp: u32) -> bool {
29 !(self.gp_offset > 48 - num_gp * 8 || self.fp_offset > 304 - num_fp * 16)
30 }
31
32 unsafe fn get_gp<T>(&mut self) -> T {
33 let n_gp = (mem::size_of::<T>() + 7) / 8;
34 assert!(self.check_space(n_gp as u32, 0));
35 let rv = ptr::read((self.reg_save_area as usize + self.gp_offset as usize) as *const _);
36 self.gp_offset += (8 * n_gp) as u32;
37 rv
38 }
39
40 unsafe fn get_overflow<T>(&mut self) -> T {
41 let align = mem::align_of::<T>();
42 let addr = self.overflow_arg_area as usize;
45 if align > 8 {
46 if addr % 16 != 0 {
47 self.overflow_arg_area = ((addr + 15) & !(16 - 1)) as *const _;
48 }
49 } else {
50 if addr % 8 != 0 {
51 self.overflow_arg_area = ((addr + 7) & !(8 - 1)) as *const _;
52 }
53 }
54 let rv = ptr::read(self.overflow_arg_area as *const _);
56 self.overflow_arg_area =
57 ((self.overflow_arg_area as usize) + mem::size_of::<T>()) as *const _;
58 rv
59 }
60}
61
62
63impl<T: 'static> VaPrimitive for *const T {
64 unsafe fn get(list: &mut VaList) -> Self {
65 <usize>::get(list) as *const T
66 }
67}
68
69macro_rules! impl_va_prim {
70 ($u: ty, $s: ty) => {
71 impl VaPrimitive for $u {
72 unsafe fn get(list: &mut VaList) -> Self {
73 let inner = list.inner();
74 if !inner.check_space(1, 0) {
76 inner.get_overflow()
77 } else {
78 inner.get_gp()
79 }
80 }
81 }
82 impl VaPrimitive for $s {
83 unsafe fn get(list: &mut VaList) -> Self {
84 mem::transmute(<$u>::get(list))
85 }
86 }
87 };
88}
89
90impl_va_prim!{ usize, isize }
91impl_va_prim!{ u64, i64 }
92impl_va_prim!{ u32, i32 }
93