diff options
| author | Triang3l <triang3l@yandex.ru> | 2024-05-12 17:23:40 +0300 |
|---|---|---|
| committer | Triang3l <triang3l@yandex.ru> | 2024-05-12 17:28:16 +0300 |
| commit | f0ad4f458735e8f843cc4f058c8cfec9206f4f0f (patch) | |
| tree | 5197ceba21c379976ea88a6dafa23f586411e940 /src | |
| parent | a90f83d44c47abfae91e2598a07a0eee0355fa68 (diff) | |
[Base] Add aliasing-safe xe::memory::Reinterpret
Accessing the same memory as different types (other than char) using
reinterpret_cast or a union is undefined behavior that has already caused
issues like #1971.
Also adds a XE_RESTRICT_VAR definition for declaring non-aliasing pointers
in performance-critical areas in the future.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xenia/base/memory.h | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h index 14fb65968..3ed4dc3ab 100644 --- a/src/xenia/base/memory.h +++ b/src/xenia/base/memory.h @@ -16,6 +16,7 @@ #include <functional> #include <string> #include <string_view> +#include <type_traits> #include "xenia/base/assert.h" #include "xenia/base/byte_order.h" @@ -24,6 +25,30 @@ namespace xe { namespace memory { +// For variable declarations (not return values or `this` pointer). +// Not propagated. +#define XE_RESTRICT_VAR __restrict + +// Aliasing-safe bit reinterpretation. +// For more complex cases such as non-trivially-copyable types, write copying +// code respecting the requirements for them externally instead of using these +// functions. + +template <typename Dst, typename Src> +void Reinterpret(Dst& XE_RESTRICT_VAR dst, const Src& XE_RESTRICT_VAR src) { + static_assert(sizeof(Dst) == sizeof(Src)); + static_assert(std::is_trivially_copyable_v<Dst>); + static_assert(std::is_trivially_copyable_v<Src>); + std::memcpy(&dst, &src, sizeof(Dst)); +} + +template <typename Dst, typename Src> +Dst Reinterpret(const Src& XE_RESTRICT_VAR src) { + Dst dst; + Reinterpret(dst, src); + return dst; +} + #if XE_PLATFORM_ANDROID void AndroidInitialize(); void AndroidShutdown(); |
