1 use std::{mem, ptr};
2 use super::VaPrimitive;
3 
4 #[repr(C)]
5 pub struct VaList(*mut VaListInner);
6 
7 #[repr(C)]
8 #[derive(Debug)]
9 #[doc(hidden)]
10 pub struct VaListInner {
11     stack: *const u64,
12     gr_top: *const u64,
13     vr_top: *const u64,
14     gr_offs: i32,
15     vr_offs: i32,
16 }
17 
18 impl VaList {
inner(&mut self) -> &mut VaListInner19     fn inner(&mut self) -> &mut VaListInner {
20         // This pointer should be valid
21         unsafe { &mut *self.0 }
22     }
23 }
24 
25 impl VaListInner {
get_gr<T>(&mut self) -> T26     pub unsafe fn get_gr<T>(&mut self) -> T {
27         assert!(!self.gr_top.is_null());
28         let rv = ptr::read((self.gr_top as usize - self.gr_offs.abs() as usize) as *const _);
29         self.gr_offs += 8;
30         rv
31     }
32 
get_vr<T>(&mut self) -> T33     pub unsafe fn get_vr<T>(&mut self) -> T {
34         assert!(!self.vr_top.is_null());
35         let rv = ptr::read((self.vr_top as usize - self.vr_offs.abs() as usize) as *const _);
36         self.vr_offs += 16;
37         rv
38     }
39 }
40 
41 impl<T: 'static> VaPrimitive for *const T {
get(list: &mut VaList) -> Self42     unsafe fn get(list: &mut VaList) -> Self {
43         <usize>::get(list) as *const T
44     }
45 }
46 
47 macro_rules! impl_va_prim_gr {
48     ($u: ty, $s: ty) => {
49         impl VaPrimitive for $u {
50             unsafe fn get(list: &mut VaList) -> Self {
51                 list.inner().get_gr()
52             }
53         }
54         impl VaPrimitive for $s {
55             unsafe fn get(list: &mut VaList) -> Self {
56                 mem::transmute(<$u>::get(list))
57             }
58         }
59     };
60 }
61 
62 macro_rules! impl_va_prim_vr {
63     ($($t:ty),+) => {
64         $(
65             impl VaPrimitive for $t {
66                 unsafe fn get(list: &mut VaList) -> Self {
67                     list.inner().get_vr()
68                 }
69             }
70         )+
71     };
72 }
73 
74 impl_va_prim_gr!{ usize, isize }
75 impl_va_prim_gr!{ u64, i64 }
76 impl_va_prim_gr!{ u32, i32 }
77 impl_va_prim_vr!{ f64, f32 }
78