summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/delegate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/delegate.cpp')
-rw-r--r--src/lib/util/delegate.cpp114
1 files changed, 65 insertions, 49 deletions
diff --git a/src/lib/util/delegate.cpp b/src/lib/util/delegate.cpp
index 7b4ee8df76e..fb2fd4e2091 100644
--- a/src/lib/util/delegate.cpp
+++ b/src/lib/util/delegate.cpp
@@ -1,79 +1,95 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles,Vas Crabb
/***************************************************************************
- delegate.c
+ delegate.cpp
Templates and classes to enable delegates for callbacks.
***************************************************************************/
-#include <assert.h>
-#include <cstdint>
-#include <stdio.h>
#include "delegate.h"
+#include "mfpresolve.h"
+
+#include <cstdio>
+#include <sstream>
+
//**************************************************************************
-// GLOBAL VARIABLES
+// MACROS
//**************************************************************************
-#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_COMPATIBLE)
+#if defined(MAME_DELEGATE_LOG_ADJ)
+ #define LOG(...) printf(__VA_ARGS__)
+#else
+ #define LOG(...) do { if (false) printf(__VA_ARGS__); } while (false)
+#endif
-delegate_mfp::raw_mfp_data delegate_mfp::s_null_mfp = { {0 }};
-#endif
+//**************************************************************************
+// LATE BINDING EXCEPTION
+//**************************************************************************
+binding_type_exception::binding_type_exception(std::type_info const &target_type, std::type_info const &actual_type)
+ : m_target_type(&target_type)
+ , m_actual_type(&actual_type)
+{
+ std::ostringstream os;
+ os << "Error performing late bind of function expecting type " << target_type.name() << " to instance of type " << actual_type.name();
+ m_what = os.str();
+}
+
+
+char const *binding_type_exception::what() const noexcept
+{
+ return m_what.c_str();
+}
+
+
+
+namespace util::detail {
//**************************************************************************
-// INTERNAL DELEGATE HELPERS
+// GLOBAL VARIABLES
//**************************************************************************
-#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL)
+const delegate_mfp_compatible::raw_mfp_data delegate_mfp_compatible::s_null_mfp = { { 0 } };
+
+
+//**************************************************************************
+// INTERNAL DELEGATE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// delegate_mfp_itanium::convert_to_generic -
+// given an object pointer and member function
+// pointer, apply the displacement and get the
+// actual function pointer
//-------------------------------------------------
-// delegate_convert_raw - given an object and an raw function, adjust the object base
-// and return the actual final code pointer
-//-------------------------------------------------//
-delegate_generic_function delegate_mfp::convert_to_generic(delegate_generic_class *&object) const
+delegate_generic_function delegate_mfp_itanium::convert_to_generic(delegate_generic_class *&object) const
{
-#if defined(__arm__) || defined(__ARMEL__) || defined(__aarch64__) || defined(__MIPSEL__) || defined(__mips_isa_rev) || defined(__mips64) || defined(__EMSCRIPTEN__)
- if ((m_this_delta & 1) == 0) {
-#if defined(LOG_DELEGATES)
- printf("Calculated Addr = %08x\n", (uintptr_t)(void*)(m_function));
-#endif
- object = reinterpret_cast<delegate_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
- return reinterpret_cast<delegate_generic_function>(m_function);
- }
- object = reinterpret_cast<delegate_generic_class *>(reinterpret_cast<std::uint8_t *>(object));
-
- // otherwise, it is the byte index into the vtable where the actual function lives
- std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object);
-#if defined(LOG_DELEGATES)
- printf("Calculated Addr = %08x (VTAB)\n", (uintptr_t)(void*)(*reinterpret_cast<delegate_generic_function *>(vtable_base + m_function + m_this_delta - 1)));
-#endif
- return *reinterpret_cast<delegate_generic_function *>(vtable_base + m_function + m_this_delta - 1);
-#else
- // apply the "this" delta to the object first
- object = reinterpret_cast<delegate_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ auto const [entrypoint, adjusted] = resolve_member_function_itanium(m_function, m_this_delta, object);
+ object = reinterpret_cast<delegate_generic_class *>(adjusted);
+ return reinterpret_cast<delegate_generic_function>(entrypoint);
+}
- // if the low bit of the vtable index is clear, then it is just a raw function pointer
- if (!(m_function & 1)) {
-#if defined(LOG_DELEGATES)
- printf("Calculated Addr = %08x\n", (uintptr_t)(void*)(m_function));
-#endif
- return reinterpret_cast<delegate_generic_function>(m_function);
- }
- // otherwise, it is the byte index into the vtable where the actual function lives
- std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object);
-#if defined(LOG_DELEGATES)
- printf("Calculated Addr = %08x (VTAB)\n", (uintptr_t)(void*)(*reinterpret_cast<delegate_generic_function *>(vtable_base + m_function - 1)));
-#endif
- return *reinterpret_cast<delegate_generic_function *>(vtable_base + m_function - 1);
-#endif
+//-------------------------------------------------
+// delegate_mfp_msvc::adjust_this_pointer - given
+// an object pointer and member function pointer,
+// apply the displacement, and walk past
+// recognisable thunks
+//-------------------------------------------------
+
+delegate_generic_function delegate_mfp_msvc::adjust_this_pointer(delegate_generic_class *&object) const
+{
+ auto const [entrypoint, adjusted] = resolve_member_function_msvc(&m_function, m_size, object);
+ object = reinterpret_cast<delegate_generic_class *>(adjusted);
+ return reinterpret_cast<delegate_generic_function>(entrypoint);
}
-#endif
+} // namespace util::detail