Skip to content

Instantly share code, notes, and snippets.

@lovely-error
Last active February 16, 2025 00:57
Show Gist options
  • Save lovely-error/3d89fe6fe55755a8c2c8c07975f94603 to your computer and use it in GitHub Desktop.
Save lovely-error/3d89fe6fe55755a8c2c8c07975f94603 to your computer and use it in GitHub Desktop.
tagged ptr
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
#[repr(C)] #[derive(Copy, Clone)]
union TaggedPtr64Repr<T> {
num: u64,
tag: ManuallyDrop<T>,
}
struct TaggedPtr64<Tag, Target>(u64, PhantomData<(*mut Target ,Tag)>);
impl <T, P> TaggedPtr64<T, P> {
fn pack(
tag: T,
ptr: *mut P
) -> Self {
const {
assert!(size_of::<T>() <= 2, "Invalid tag size");
assert!(align_of::<T>() <= 8, "Invalid tag align");
}
let ptr = (ptr as u64) << 16;
let mut val = TaggedPtr64Repr { num: ptr };
val.tag = ManuallyDrop::new(tag);
let val = unsafe { val.num };
return Self(val, PhantomData);
}
fn unpack(self) -> (T, *mut P) {
let Self(val, _) = self;
let val = TaggedPtr64Repr { num: val };
let ptr = unsafe { val.num } >> 16;
let ptr = ptr as *mut P;
let tag = unsafe { val.tag };
let tag = ManuallyDrop::into_inner(tag);
return (tag, ptr);
}
pub fn tag_ref(&mut self) -> &mut T {
unsafe { transmute(self) }
}
}
impl <T, P> Clone for TaggedPtr64<T, P> where T: Copy {
fn clone(&self) -> Self {
Self(self.0, PhantomData)
}
}
impl <T, P> Copy for TaggedPtr64<T, P> where T: Copy {}
fn main () {
let mut val = 13137;
let ptr = TaggedPtr64::pack(13137u16, &mut val);
let a@(tag, ptr) = ptr.unpack();
println!("{:?}", a);
assert!(tag == 13137 && ptr == &mut val);
assert!(unsafe { *ptr } == 13137);
let mut ptr = TaggedPtr64::pack(tag, unsafe {&mut *ptr});
*ptr.tag_ref() += 1;
let a@(tag, ptr) = ptr.unpack();
println!("{:?}", a);
assert!(tag == 13138);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment