summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/mfpresolve.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/mfpresolve.h')
-rw-r--r--src/lib/util/mfpresolve.h86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/lib/util/mfpresolve.h b/src/lib/util/mfpresolve.h
new file mode 100644
index 00000000000..c9a2eba6a95
--- /dev/null
+++ b/src/lib/util/mfpresolve.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ mfpresolve.h
+
+ Helpers for resolving member function pointers to entry points.
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_MFPRESOLVE_H
+#define MAME_LIB_UTIL_MFPRESOLVE_H
+
+#pragma once
+
+#include "abi.h"
+
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+
+namespace util {
+
+namespace detail {
+
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_itanium(std::uintptr_t function, std::ptrdiff_t delta, void const *object) noexcept;
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_msvc(void const *funcptr, std::size_t size, void const *object) noexcept;
+std::uintptr_t bypass_member_function_thunks(std::uintptr_t entrypoint, void const *object) noexcept;
+
+} // namespace detail
+
+
+template <typename T, typename U>
+inline T bypass_member_function_thunks(T entrypoint, U const *object) noexcept
+{
+ return reinterpret_cast<T>(
+ detail::bypass_member_function_thunks(
+ reinterpret_cast<std::uintptr_t>(entrypoint),
+ reinterpret_cast<void const *>(object)));
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T::*function)(Params...), T *object) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ struct { uintptr_t ptr; ptrdiff_t adj; } equiv;
+ static_assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.ptr, equiv.adj, object);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function), object);
+ }
+ else
+ {
+ return std::make_pair(std::uintptr_t(nullptr), std::uintptr_t(nullptr));
+ }
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T::*function)(Params...) const, T const *object) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ struct { uintptr_t ptr; ptrdiff_t adj; } equiv;
+ static_assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.ptr, equiv.adj, object);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function), object);
+ }
+ else
+ {
+ return std::make_pair(std::uintptr_t(nullptr), std::uintptr_t(nullptr));
+ }
+}
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_MFPRESOLVE_H