diff options
Diffstat (limited to 'src/lib/util/delegate.cpp')
-rw-r--r-- | src/lib/util/delegate.cpp | 114 |
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 |