summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTriang3l <triang3l@yandex.ru>2024-05-12 17:23:40 +0300
committerTriang3l <triang3l@yandex.ru>2024-05-12 17:28:16 +0300
commitf0ad4f458735e8f843cc4f058c8cfec9206f4f0f (patch)
tree5197ceba21c379976ea88a6dafa23f586411e940 /src
parenta90f83d44c47abfae91e2598a07a0eee0355fa68 (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.h25
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();