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