diff --git a/src/util/tptr.h b/src/util/tptr.h index 37b6f64fe..99abe34a7 100644 --- a/src/util/tptr.h +++ b/src/util/tptr.h @@ -21,6 +21,7 @@ Revision History: #include #include "util/machine.h" +#include "util/debug.h" #define TAG_SHIFT PTR_ALIGNMENT #define ALIGNMENT_VALUE (1 << PTR_ALIGNMENT) @@ -42,4 +43,22 @@ Revision History: #define UNBOXINT(PTR) static_cast(reinterpret_cast(PTR) >> PTR_ALIGNMENT) +template +U unbox(T* ptr) { + return static_cast(reinterpret_cast(ptr) >> PTR_ALIGNMENT); +} +template +unsigned get_tag(T* ptr) { + return reinterpret_cast(ptr) & TAG_MASK; +} + +template +T* box(U val, std::uintptr_t tag = 0) { + static_assert( sizeof(T*) >= sizeof(U) + PTR_ALIGNMENT ); + SASSERT_EQ(tag & PTR_MASK, 0); + T* ptr = reinterpret_cast((static_cast(val) << PTR_ALIGNMENT) | tag); + SASSERT_EQ(val, unbox(ptr)); // roundtrip of conversion integer -> pointer -> integer is not actually guaranteed by the C++ standard (but seems fine in practice, as indicated by previous usage of BOXINT/UNBOXINT) + SASSERT_EQ(tag, get_tag(ptr)); + return ptr; +}