summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/delegate.cpp
blob: 67fb7e72d429689371c5c9256491c851480c91a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// license:BSD-3-Clause
// copyright-holders:Aaron Giles,Vas Crabb
/***************************************************************************

    delegate.cpp

    Templates and classes to enable delegates for callbacks.

***************************************************************************/

#include "delegate.h"

#include "mfpresolve.h"

#include <cstdio>
#include <sstream>


//**************************************************************************
//  MACROS
//**************************************************************************

#if defined(MAME_DELEGATE_LOG_ADJ)
	#define LOG(...) printf(__VA_ARGS__)
#else
	#define LOG(...) do { if (false) printf(__VA_ARGS__); } while (false)
#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 {

//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

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_generic_function delegate_mfp_itanium::convert_to_generic(delegate_generic_class *&object) const
{
	auto const [entrypoint, adjusted] = detail::resolve_member_function_itanium(m_function, m_this_delta, object);
	object = reinterpret_cast<delegate_generic_class *>(adjusted);
	return reinterpret_cast<delegate_generic_function>(entrypoint);
}


//-------------------------------------------------
//  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] = detail::resolve_member_function_msvc(&m_function, m_size, object);
	object = reinterpret_cast<delegate_generic_class *>(adjusted);
	return reinterpret_cast<delegate_generic_function>(entrypoint);
}

} // namespace util::detail